diff --git a/apps/ledger-live-desktop/src/config/urls.ts b/apps/ledger-live-desktop/src/config/urls.ts index b49cb8435470..84bb87a245e0 100644 --- a/apps/ledger-live-desktop/src/config/urls.ts +++ b/apps/ledger-live-desktop/src/config/urls.ts @@ -7,6 +7,7 @@ export const supportLinkByTokenType = { "https://support.ledger.com/hc/articles/360013062159?utm_source=ledger_live_desktop&utm_medium=self_referral&utm_content=receive_account_flow", asa: "https://support.ledger.com/hc/articles/360015896040?utm_source=ledger_live_desktop&utm_medium=self_referral&utm_content=receive_account_flow", nfts: "https://support.ledger.com/hc/articles/4404389453841-Receive-crypto-assets?utm_medium=self_referral&utm_content=receive_account_flow", + // spl: "Solana spl tokens. TODO: to be defined", }; const errors: Record = { @@ -183,6 +184,7 @@ export const urls = { }, solana: { staking: "https://support.ledger.com/hc/articles/4731749170461?docs=true", + splTokenInfo: "Solana spl tokens link TODO: to be defined", recipient_info: "https://support.ledger.com", ledgerByFigmentTC: "https://cdn.figment.io/legal/Current%20Ledger_Online%20Staking%20Delgation%20Services%20Agreement.pdf", diff --git a/apps/ledger-live-desktop/src/renderer/families/solana/TransactionConfirmFields.tsx b/apps/ledger-live-desktop/src/renderer/families/solana/TransactionConfirmFields.tsx new file mode 100644 index 000000000000..877c580773c9 --- /dev/null +++ b/apps/ledger-live-desktop/src/renderer/families/solana/TransactionConfirmFields.tsx @@ -0,0 +1,67 @@ +import React, { useMemo } from "react"; +import { getDeviceTransactionConfig } from "@ledgerhq/live-common/transaction/index"; +import { SolanaFamily } from "./types"; +import Alert from "~/renderer/components/Alert"; +import { Trans } from "react-i18next"; +import ConfirmTitle from "~/renderer/components/TransactionConfirm/ConfirmTitle"; +import LinkWithExternalIcon from "~/renderer/components/LinkWithExternalIcon"; +import Box from "~/renderer/components/Box"; +import { openURL } from "~/renderer/linking"; +import { useLocalizedUrl } from "~/renderer/hooks/useLocalizedUrls"; +import { urls } from "~/config/urls"; + +const Title: TitleComponent = props => { + const { transaction, account, parentAccount, status } = props; + const transferTokenHelpUrl = useLocalizedUrl(urls.solana.splTokenInfo); + + const fields = getDeviceTransactionConfig({ + account, + parentAccount, + transaction, + status, + }); + + const typeTransaction: string | undefined = useMemo(() => { + const typeField = fields.find(field => field.label && field.label === "Type"); + + if (typeField && typeField.type === "text" && typeField.value) { + return typeField.value; + } + }, [fields]); + + if (transaction.model.commandDescriptor?.command.kind === "token.transfer") { + return ( + + + + + openURL(transferTokenHelpUrl)} + /> + + + + ); + } + + return ; +}; + +type TransactionConfirmFields = SolanaFamily["transactionConfirmFields"]; +type TitleComponent = NonNullable["title"]>; + +const transactionConfirmFields: TransactionConfirmFields = { + // footer: Footer, // is not shown without manifestId + // fieldComponents, + title: Title, +}; + +export default transactionConfirmFields; diff --git a/apps/ledger-live-desktop/src/renderer/families/solana/index.ts b/apps/ledger-live-desktop/src/renderer/families/solana/index.ts index da1314ef035f..3396136c9ec2 100644 --- a/apps/ledger-live-desktop/src/renderer/families/solana/index.ts +++ b/apps/ledger-live-desktop/src/renderer/families/solana/index.ts @@ -6,6 +6,7 @@ import AccountBalanceSummaryFooter from "./AccountBalanceSummaryFooter"; import StakeBanner from "./StakeBanner"; import { SolanaFamily } from "./types"; import operationDetails from "./operationDetails"; +import transactionConfirmFields from "./TransactionConfirmFields"; const family: SolanaFamily = { accountHeaderManageActions, @@ -15,6 +16,7 @@ const family: SolanaFamily = { AccountBalanceSummaryFooter, StakeBanner, operationDetails, + transactionConfirmFields, }; export default family; diff --git a/apps/ledger-live-desktop/static/i18n/en/app.json b/apps/ledger-live-desktop/static/i18n/en/app.json index 91b7b62c0338..d5fc015b00a1 100644 --- a/apps/ledger-live-desktop/static/i18n/en/app.json +++ b/apps/ledger-live-desktop/static/i18n/en/app.json @@ -3697,7 +3697,8 @@ } }, "token": { - "frozenStateWarning": "Account assets are frozen!" + "frozenStateWarning": "Account assets are frozen!", + "transferWarning": "Solana SPL tokens transactions have unique characteristics. To learn more, visit: <0>ledger.com/spl" } }, "ethereum": { diff --git a/apps/ledger-live-mobile/src/families/solana/TransactionConfirmFields.tsx b/apps/ledger-live-mobile/src/families/solana/TransactionConfirmFields.tsx new file mode 100644 index 000000000000..4bf31f76ebfd --- /dev/null +++ b/apps/ledger-live-mobile/src/families/solana/TransactionConfirmFields.tsx @@ -0,0 +1,46 @@ +import invariant from "invariant"; +import React from "react"; +import { Linking, View } from "react-native"; +import { Trans } from "react-i18next"; +import { Link } from "@ledgerhq/native-ui"; +import { DeviceTransactionField } from "@ledgerhq/live-common/transaction/index"; +import { + SolanaAccount, + SolanaTokenAccount, + Transaction, + TransactionStatus, +} from "@ledgerhq/live-common/families/solana/types"; +import Alert from "~/components/Alert"; +import { urls } from "~/utils/urls"; +import LText from "~/components/LText"; + +type SolanaFieldComponentProps = { + account: SolanaAccount | SolanaTokenAccount; + parentAccount: SolanaAccount | undefined | null; + transaction: Transaction; + status: TransactionStatus; + field: DeviceTransactionField; +}; + +const Warning = ({ transaction }: SolanaFieldComponentProps) => { + invariant(transaction.family === "solana", "solana transaction"); + if (transaction.model.commandDescriptor?.command.kind === "token.transfer") { + return ( + + + + + Linking.openURL(urls.solana.splTokenInfo)} type="color" /> + + + + + ); + } + return null; +}; + +export default { + warning: Warning, + fieldComponents: {}, +}; diff --git a/apps/ledger-live-mobile/src/locales/en/common.json b/apps/ledger-live-mobile/src/locales/en/common.json index b4f9169197ea..9febd8f2fab2 100644 --- a/apps/ledger-live-mobile/src/locales/en/common.json +++ b/apps/ledger-live-mobile/src/locales/en/common.json @@ -5844,7 +5844,8 @@ "reserveWarning": "Please ensure you reserve at least {{amount}} SOL in your wallet to cover future network fees to deactivate and withdraw your stake" }, "token": { - "frozenStateWarning": "Account assets are frozen!" + "frozenStateWarning": "Account assets are frozen!", + "transferWarning": "Double-check the transaction details on your Ledger device before signing. Solana SPL tokens transactions have unique characteristics. To learn more, visit: <0>ledger.com/spl" } }, "near": { diff --git a/apps/ledger-live-mobile/src/utils/urls.tsx b/apps/ledger-live-mobile/src/utils/urls.tsx index 65b41fd7f44a..b324549bd55a 100644 --- a/apps/ledger-live-mobile/src/utils/urls.tsx +++ b/apps/ledger-live-mobile/src/utils/urls.tsx @@ -191,6 +191,7 @@ export const urls = { solana: { supportPage: "https://support.ledger.com", stakingPage: "https://support.ledger.com/hc/en-us/articles/4731749170461?docs=true", + splTokenInfo: "Solana spl tokens link TODO: to be defined", }, resources: { gettingStarted: diff --git a/libs/coin-modules/coin-solana/src/deviceTransactionConfig.ts b/libs/coin-modules/coin-solana/src/deviceTransactionConfig.ts index 965a1997afe0..93500d8d4987 100644 --- a/libs/coin-modules/coin-solana/src/deviceTransactionConfig.ts +++ b/libs/coin-modules/coin-solana/src/deviceTransactionConfig.ts @@ -70,55 +70,23 @@ function fieldsForTransfer(_command: TransferCommand): DeviceTransactionField[] return fields; } -function fieldsForTokenTransfer(command: TokenTransferCommand): DeviceTransactionField[] { +function fieldsForTokenTransfer(_command: TokenTransferCommand): DeviceTransactionField[] { const fields: Array = []; - if (command.recipientDescriptor.shouldCreateAsAssociatedTokenAccount) { - fields.push({ - type: "address", - label: "Create token acct", - address: command.recipientDescriptor.tokenAccAddress, - }); - - fields.push({ - type: "address", - label: "From mint", - address: command.mintAddress, - }); - fields.push({ - type: "address", - label: "Funded by", - address: command.ownerAddress, - }); - } - fields.push({ type: "amount", label: "Transfer tokens", }); fields.push({ - type: "address", - address: command.mintAddress, - label: "Mint", - }); - - fields.push({ - type: "address", - address: command.ownerAssociatedTokenAccountAddress, - label: "From", - }); - - fields.push({ - type: "address", - address: command.ownerAddress, - label: "Owner", + type: "text", + value: "Solana", + label: "Network", }); fields.push({ - type: "address", - address: command.ownerAddress, - label: "Fee payer", + type: "fees", + label: "Max network fees", }); return fields;