diff --git a/.changeset/unlucky-clocks-beg.md b/.changeset/unlucky-clocks-beg.md new file mode 100644 index 000000000000..d031bd99efc2 --- /dev/null +++ b/.changeset/unlucky-clocks-beg.md @@ -0,0 +1,6 @@ +--- +"ledger-live-desktop": minor +"live-mobile": minor +--- + +Adds LNS error on LLM when swapping unsupported assets. Updates translations diff --git a/apps/ledger-live-desktop/static/i18n/en/app.json b/apps/ledger-live-desktop/static/i18n/en/app.json index 9c6317b1bb9c..5b48eddb6c29 100644 --- a/apps/ledger-live-desktop/static/i18n/en/app.json +++ b/apps/ledger-live-desktop/static/i18n/en/app.json @@ -443,12 +443,12 @@ "changeProvider": "Swap with another provider" }, "incompatibility": { - "ton_title": "Ledger Nano S™ does not support swapping Ton through Ledger Live", - "ton_description": "To swap Ton through Ledger Live, use any other compatible Ledger device, such as the Ledger Nano S Plus™, Ledger Nano X™, Ledger Flex™ or Ledger Stax™.", - "spl_tokens_title": "Ledger Nano S™ does not support swapping Solana tokens through Ledger Live", - "spl_tokens_description": "To swap Solana tokens through Ledger Live, use any other compatible Ledger device, such as the Ledger Nano S Plus™, Ledger Nano X™, Ledger Flex™ or Ledger Stax™.", - "ada_title": "Ledger Nano S™ does not support swapping Cardano through Ledger Live", - "ada_description": "To swap Cardano through Ledger Live, use any other compatible Ledger device, such as the Ledger Nano S Plus™, Ledger Nano X™, Ledger Flex™ or Ledger Stax™." + "ton_title": "Ledger Nano S™ does not support swapping Ton", + "ton_description": "To swap Ton, use any other compatible Ledger device, such as the Ledger Nano S Plus™, Ledger Nano X™, Ledger Flex™ or Ledger Stax™.", + "spl_tokens_title": "Ledger Nano S™ does not support swapping Solana tokens", + "spl_tokens_description": "To swap Solana tokens, use any other compatible Ledger device, such as the Ledger Nano S Plus™, Ledger Nano X™, Ledger Flex™ or Ledger Stax™.", + "ada_title": "Ledger Nano S™ does not support swapping Cardano", + "ada_description": "To swap Cardano, use any other compatible Ledger device, such as the Ledger Nano S Plus™, Ledger Nano X™, Ledger Flex™ or Ledger Stax™." }, "providers": { "title": "Choose a provider to swap crypto", diff --git a/apps/ledger-live-mobile/assets/images/swap/nanoSBackdropFilter.png b/apps/ledger-live-mobile/assets/images/swap/nanoSBackdropFilter.png new file mode 100644 index 000000000000..3c9609d0c8d7 Binary files /dev/null and b/apps/ledger-live-mobile/assets/images/swap/nanoSBackdropFilter.png differ diff --git a/apps/ledger-live-mobile/src/components/DeviceAction/rendering.tsx b/apps/ledger-live-mobile/src/components/DeviceAction/rendering.tsx index ea38181087ca..77cff348619c 100644 --- a/apps/ledger-live-mobile/src/components/DeviceAction/rendering.tsx +++ b/apps/ledger-live-mobile/src/components/DeviceAction/rendering.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useState } from "react"; -import { Platform, ScrollView } from "react-native"; +import { Image, Linking, Platform, ScrollView } from "react-native"; import { useSelector } from "react-redux"; import styled from "styled-components/native"; import { @@ -63,6 +63,7 @@ import { WalletState, accountNameWithDefaultSelector } from "@ledgerhq/live-wall import { SettingsState } from "~/reducers/types"; import { RootStackParamList } from "../RootNavigator/types/RootNavigator"; import { isSyncOnboardingSupported } from "@ledgerhq/live-common/device/use-cases/screenSpecs"; +import { DeviceModelId } from "@ledgerhq/types-devices"; export const Wrapper = styled(Flex).attrs({ flex: 1, @@ -1084,3 +1085,57 @@ export const AutoRepair = ({ ); }; + +const HARDWARE_UPDATE_ASSETS: Partial> = { + nanoS: require("../../../assets/images/swap/nanoSBackdropFilter.png"), +}; + +export const HardwareUpdate = ({ + t, + device, + i18nKeyTitle, + i18nKeyDescription, +}: { + t: RawProps["t"]; + device: Device; + i18nKeyTitle: string; + i18nKeyDescription: string; +}) => { + const openUrl = (url: string) => Linking.openURL(url); + + return ( + + + + + + {t(i18nKeyTitle)} + + + {t(i18nKeyDescription)} + + + + + ); +}; diff --git a/apps/ledger-live-mobile/src/locales/en/common.json b/apps/ledger-live-mobile/src/locales/en/common.json index 9e9109e52f0e..091fb5f75f24 100644 --- a/apps/ledger-live-mobile/src/locales/en/common.json +++ b/apps/ledger-live-mobile/src/locales/en/common.json @@ -3470,6 +3470,16 @@ "providers": { "noProviders": "No results found. There are no quotes available with the current preferences." } + }, + "incompatibility": { + "explore_compatible_devices": "Explore compatible devices", + "contact_support": "Contact customer support", + "ton_title": "Ledger Nano S™ does not support swapping Ton", + "ton_description": "To swap Ton, use any other compatible Ledger device, such as the Ledger Nano S Plus™, Ledger Nano X™, Ledger Flex™ or Ledger Stax™.", + "spl_tokens_title": "Ledger Nano S™ does not support swapping Solana tokens", + "spl_tokens_description": "To swap Solana tokens, use any other compatible Ledger device, such as the Ledger Nano S Plus™, Ledger Nano X™, Ledger Flex™ or Ledger Stax™.", + "ada_title": "Ledger Nano S™ does not support swapping Cardano", + "ada_description": "To swap Cardano, use any other compatible Ledger device, such as the Ledger Nano S Plus™, Ledger Nano X™, Ledger Flex™ or Ledger Stax™." } }, "lending": { diff --git a/apps/ledger-live-mobile/src/screens/Swap/Form/Modal/Confirmation.tsx b/apps/ledger-live-mobile/src/screens/Swap/Form/Modal/Confirmation.tsx index 127e573defc4..dfb00021f9de 100644 --- a/apps/ledger-live-mobile/src/screens/Swap/Form/Modal/Confirmation.tsx +++ b/apps/ledger-live-mobile/src/screens/Swap/Form/Modal/Confirmation.tsx @@ -20,7 +20,7 @@ import { Device } from "@ledgerhq/live-common/hw/actions/types"; import { postSwapAccepted, postSwapCancelled } from "@ledgerhq/live-common/exchange/swap/index"; import { InstalledItem } from "@ledgerhq/live-common/apps/types"; import { useBroadcast } from "@ledgerhq/live-common/hooks/useBroadcast"; -import { renderLoading } from "~/components/DeviceAction/rendering"; +import { HardwareUpdate, renderLoading } from "~/components/DeviceAction/rendering"; import { updateAccountWithUpdater } from "~/actions/accounts"; import DeviceAction from "~/components/DeviceAction"; import QueuedDrawer from "~/components/QueuedDrawer"; @@ -32,6 +32,7 @@ import type { SwapNavigatorParamList } from "~/components/RootNavigator/types/Sw import { useInitSwapDeviceAction, useTransactionDeviceAction } from "~/hooks/deviceActions"; import { BigNumber } from "bignumber.js"; import { mevProtectionSelector } from "~/reducers/settings"; +import { DeviceModelId } from "@ledgerhq/devices"; export type DeviceMeta = { result: { installed: InstalledItem[] } | null | undefined; @@ -49,6 +50,43 @@ interface Props { } type NavigationProp = StackNavigatorNavigation; +type Keys = Record; + +const INCOMPATIBLE_NANO_S_TOKENS_KEYS: Keys = { + solana: { + title: "transfer.swap2.incompatibility.spl_tokens_title", + description: "transfer.swap2.incompatibility.spl_tokens_description", + }, +}; + +const INCOMPATIBLE_NANO_S_CURRENCY_KEYS: Keys = { + ton: { + title: "transfer.swap2.incompatibility.ton_title", + description: "transfer.swap2.incompatibility.ton_description", + }, + cardano: { + title: "transfer.swap2.incompatibility.ada_title", + description: "transfer.swap2.incompatibility.ada_description", + }, +}; + +const getIncompatibleCurrencyKeys = (exchange: ExchangeSwap) => { + const parentFrom = + (exchange?.fromAccount?.type === "TokenAccount" && exchange?.fromParentAccount?.currency?.id) || + ""; + const parentTo = + (exchange?.toAccount?.type === "TokenAccount" && exchange?.toParentAccount?.currency?.id) || ""; + const from = + (exchange?.fromAccount.type === "Account" && exchange?.fromAccount?.currency?.id) || ""; + const to = (exchange?.toAccount.type === "Account" && exchange?.toAccount?.currency?.id) || ""; + + return ( + INCOMPATIBLE_NANO_S_TOKENS_KEYS[parentFrom] || + INCOMPATIBLE_NANO_S_TOKENS_KEYS[parentTo] || + INCOMPATIBLE_NANO_S_CURRENCY_KEYS[from] || + INCOMPATIBLE_NANO_S_CURRENCY_KEYS[to] + ); +}; export function Confirmation({ swapTx: swapTxProp, @@ -205,6 +243,27 @@ export function Confirmation({ const { t } = useTranslation(); + const keys = getIncompatibleCurrencyKeys(exchange); + + if (deviceMeta?.device?.modelId === DeviceModelId.nanoS && keys) { + return ( + + + + + } + /> + + ); + } + return (