From 22975294cbfd93ef31ed15030864cba2dc4323b1 Mon Sep 17 00:00:00 2001 From: Thomas Brillard Date: Wed, 8 Jan 2025 12:06:11 +0100 Subject: [PATCH 1/7] feat: Uniswap's term's of use --- .changeset/afraid-falcons-eat.md | 5 +++++ .../components/TransactionConfirm/ConfirmFooter.tsx | 11 ++++++++--- .../renderer/components/TransactionConfirm/index.tsx | 1 + 3 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 .changeset/afraid-falcons-eat.md diff --git a/.changeset/afraid-falcons-eat.md b/.changeset/afraid-falcons-eat.md new file mode 100644 index 000000000000..355db78c8acc --- /dev/null +++ b/.changeset/afraid-falcons-eat.md @@ -0,0 +1,5 @@ +--- +"ledger-live-desktop": minor +--- + +feat: Uniswap's term's of use diff --git a/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx b/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx index 7b6113cb73b9..2d08e92256fc 100644 --- a/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx +++ b/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx @@ -11,9 +11,12 @@ const HorizontalSeparator = styled.div` width: 100%; `; +const uniwapUniversalRouterAddr = "0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD"; + const termsOfUse = new Map([ ["paraswap", "https://paraswap.io/tos"], ["1inch", "https://1inch.io/assets/1inch_network_terms_of_use.pdf"], + ["Uniswap", "https://support.uniswap.org/hc/en-us/requests/new"], ]); if (getEnv("PLAYWRIGHT_RUN")) { @@ -23,12 +26,14 @@ if (getEnv("PLAYWRIGHT_RUN")) { type Props = { footer: React.ReactNode | undefined; manifestId?: string | null; + transaction?: Transaction | null; manifestName?: string | null; }; -const ConfirmFooter = ({ footer, manifestId, manifestName }: Props) => { +const ConfirmFooter = ({ footer, transaction, manifestId, manifestName }: Props) => { if (!manifestId) return; - const termsOfUseUrl = termsOfUse.get(manifestId); + const appNameByAddr = transaction?.recipient === uniwapUniversalRouterAddr ? "Uniswap" : null; + const termsOfUseUrl = termsOfUse.get(appNameByAddr || manifestId); if (!termsOfUseUrl) return; return ( <> @@ -39,7 +44,7 @@ const ConfirmFooter = ({ footer, manifestId, manifestName }: Props) => { : null} + transaction={transaction} manifestId={manifestId} manifestName={manifestName} /> From 1cc0ec58af9788c023fa224ed4d0f9ef6aa46d1a Mon Sep 17 00:00:00 2001 From: Thomas Brillard Date: Fri, 10 Jan 2025 14:12:55 +0100 Subject: [PATCH 2/7] feat: privacy policy --- .../TransactionConfirm/ConfirmFooter.tsx | 62 +++++++++++++------ .../static/i18n/en/app.json | 1 + .../src/exchange/providers/swap.ts | 2 + 3 files changed, 47 insertions(+), 18 deletions(-) diff --git a/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx b/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx index 2d08e92256fc..429f6a7a78f1 100644 --- a/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx +++ b/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx @@ -4,21 +4,21 @@ import { Trans, withTranslation } from "react-i18next"; import { getEnv } from "@ledgerhq/live-env"; import Text from "~/renderer/components/Text"; import { openURL } from "~/renderer/linking"; - +import { uniwapUniversalRouterAddr } from "@ledgerhq/live-common/exchange/providers/swap"; const HorizontalSeparator = styled.div` height: 1px; background: ${p => p.theme.colors.palette.text.shade20}; width: 100%; `; -const uniwapUniversalRouterAddr = "0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD"; - const termsOfUse = new Map([ ["paraswap", "https://paraswap.io/tos"], ["1inch", "https://1inch.io/assets/1inch_network_terms_of_use.pdf"], - ["Uniswap", "https://support.uniswap.org/hc/en-us/requests/new"], + ["Uniswap", "https://uniswap.org/terms-of-service"], ]); +const privacyPolicy = new Map([["Uniswap", "https://uniswap.org/privacy-policy"]]); + if (getEnv("PLAYWRIGHT_RUN")) { termsOfUse.set("dummy-live-app", "https://localhost.io/testtos"); } @@ -34,6 +34,7 @@ const ConfirmFooter = ({ footer, transaction, manifestId, manifestName }: Props) if (!manifestId) return; const appNameByAddr = transaction?.recipient === uniwapUniversalRouterAddr ? "Uniswap" : null; const termsOfUseUrl = termsOfUse.get(appNameByAddr || manifestId); + const privacyUrl = privacyPolicy.get(appNameByAddr || manifestId); if (!termsOfUseUrl) return; return ( <> @@ -42,20 +43,45 @@ const ConfirmFooter = ({ footer, transaction, manifestId, manifestName }: Props) footer ) : ( - openURL(termsOfUseUrl)} - style={{ - cursor: "pointer", - textDecoration: "underline", - }} - />, - ]} - /> + {privacyUrl ? ( + openURL(termsOfUseUrl)} + style={{ + cursor: "pointer", + textDecoration: "underline", + }} + />, + openURL(privacyUrl)} + style={{ + cursor: "pointer", + textDecoration: "underline", + }} + />, + ]} + /> + ) : ( + openURL(termsOfUseUrl)} + style={{ + cursor: "pointer", + textDecoration: "underline", + }} + />, + ]} + /> + )} )} diff --git a/apps/ledger-live-desktop/static/i18n/en/app.json b/apps/ledger-live-desktop/static/i18n/en/app.json index b04807f6c671..eb30f6c5f914 100644 --- a/apps/ledger-live-desktop/static/i18n/en/app.json +++ b/apps/ledger-live-desktop/static/i18n/en/app.json @@ -5317,6 +5317,7 @@ "verifyData": "Always verify the operation details on your device.", "doubleCheck": "Double-check the transaction details on your Ledger device before signing.", "termsAndConditions": "By signing this transaction, you accept <0>{{appName}}'s terms of use.", + "termsAndConditionsWithPrivacy": "By signing this transaction, you accept <0>{{appName}}'s terms of use. and <1>Privacy Policy.", "warningWording": {}, "titleWording": { "send": "Please confirm on your device to finalize the operation", diff --git a/libs/ledger-live-common/src/exchange/providers/swap.ts b/libs/ledger-live-common/src/exchange/providers/swap.ts index e0a74c4bb671..2f87b8831ef6 100644 --- a/libs/ledger-live-common/src/exchange/providers/swap.ts +++ b/libs/ledger-live-common/src/exchange/providers/swap.ts @@ -143,6 +143,8 @@ const DEFAULT_SWAP_PROVIDERS: Record Date: Mon, 13 Jan 2025 09:12:05 +0100 Subject: [PATCH 3/7] chore: generic solution --- .../renderer/components/TransactionConfirm/ConfirmFooter.tsx | 4 ++-- libs/ledger-live-common/src/exchange/providers/swap.ts | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx b/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx index 429f6a7a78f1..52b568186bf2 100644 --- a/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx +++ b/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx @@ -4,7 +4,7 @@ import { Trans, withTranslation } from "react-i18next"; import { getEnv } from "@ledgerhq/live-env"; import Text from "~/renderer/components/Text"; import { openURL } from "~/renderer/linking"; -import { uniwapUniversalRouterAddr } from "@ledgerhq/live-common/exchange/providers/swap"; +import { dexProvidersContractAddress } from "@ledgerhq/live-common/exchange/providers/swap"; const HorizontalSeparator = styled.div` height: 1px; background: ${p => p.theme.colors.palette.text.shade20}; @@ -32,7 +32,7 @@ type Props = { const ConfirmFooter = ({ footer, transaction, manifestId, manifestName }: Props) => { if (!manifestId) return; - const appNameByAddr = transaction?.recipient === uniwapUniversalRouterAddr ? "Uniswap" : null; + const appNameByAddr = dexProvidersContractAddress[transaction?.recipient || ""]; const termsOfUseUrl = termsOfUse.get(appNameByAddr || manifestId); const privacyUrl = privacyPolicy.get(appNameByAddr || manifestId); if (!termsOfUseUrl) return; diff --git a/libs/ledger-live-common/src/exchange/providers/swap.ts b/libs/ledger-live-common/src/exchange/providers/swap.ts index 2f87b8831ef6..b5a331a6d1cf 100644 --- a/libs/ledger-live-common/src/exchange/providers/swap.ts +++ b/libs/ledger-live-common/src/exchange/providers/swap.ts @@ -143,7 +143,9 @@ const DEFAULT_SWAP_PROVIDERS: Record Date: Mon, 13 Jan 2025 12:43:03 +0100 Subject: [PATCH 4/7] chore: moved all data to LLC and removed Maps --- .../TransactionConfirm/ConfirmFooter.tsx | 19 ++++++++----------- .../src/exchange/providers/swap.ts | 10 ++++++++++ 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx b/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx index 52b568186bf2..7ce57914ce89 100644 --- a/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx +++ b/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx @@ -4,21 +4,18 @@ import { Trans, withTranslation } from "react-i18next"; import { getEnv } from "@ledgerhq/live-env"; import Text from "~/renderer/components/Text"; import { openURL } from "~/renderer/linking"; -import { dexProvidersContractAddress } from "@ledgerhq/live-common/exchange/providers/swap"; +import { + dexProvidersContractAddress, + privacyPolicy, + termsOfUse, +} from "@ledgerhq/live-common/exchange/providers/swap"; + const HorizontalSeparator = styled.div` height: 1px; background: ${p => p.theme.colors.palette.text.shade20}; width: 100%; `; -const termsOfUse = new Map([ - ["paraswap", "https://paraswap.io/tos"], - ["1inch", "https://1inch.io/assets/1inch_network_terms_of_use.pdf"], - ["Uniswap", "https://uniswap.org/terms-of-service"], -]); - -const privacyPolicy = new Map([["Uniswap", "https://uniswap.org/privacy-policy"]]); - if (getEnv("PLAYWRIGHT_RUN")) { termsOfUse.set("dummy-live-app", "https://localhost.io/testtos"); } @@ -33,8 +30,8 @@ type Props = { const ConfirmFooter = ({ footer, transaction, manifestId, manifestName }: Props) => { if (!manifestId) return; const appNameByAddr = dexProvidersContractAddress[transaction?.recipient || ""]; - const termsOfUseUrl = termsOfUse.get(appNameByAddr || manifestId); - const privacyUrl = privacyPolicy.get(appNameByAddr || manifestId); + const termsOfUseUrl = termsOfUse[appNameByAddr || manifestId]; + const privacyUrl = privacyPolicy[appNameByAddr || manifestId]; if (!termsOfUseUrl) return; return ( <> diff --git a/libs/ledger-live-common/src/exchange/providers/swap.ts b/libs/ledger-live-common/src/exchange/providers/swap.ts index b5a331a6d1cf..84f66ef9182f 100644 --- a/libs/ledger-live-common/src/exchange/providers/swap.ts +++ b/libs/ledger-live-common/src/exchange/providers/swap.ts @@ -147,6 +147,16 @@ export const dexProvidersContractAddress: { [key: string]: string } = { "0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD": "Uniswap", }; +export const termsOfUse: { [key: string]: string } = { + paraswap: "https://paraswap.io/tos", + "1inch": "https://1inch.io/assets/1inch_network_terms_of_use.pdf", + Uniswap: "https://uniswap.org/terms-of-service", +}; + +export const privacyPolicy: { [key: string]: string } = { + Uniswap: "https://uniswap.org/privacy-policy", +}; + type CurrencyData = { id: string; config: string; From 3bb49d33fd1c2f940bfd4c38febb57b1cbb8122e Mon Sep 17 00:00:00 2001 From: Thomas Brillard Date: Mon, 13 Jan 2025 13:17:44 +0100 Subject: [PATCH 5/7] chore: tests --- .../renderer/components/TransactionConfirm/ConfirmFooter.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx b/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx index 7ce57914ce89..85a0fa5a0457 100644 --- a/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx +++ b/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx @@ -17,7 +17,7 @@ const HorizontalSeparator = styled.div` `; if (getEnv("PLAYWRIGHT_RUN")) { - termsOfUse.set("dummy-live-app", "https://localhost.io/testtos"); + termsOfUse["dummy-live-app"] = "https://localhost.io/testtos"; } type Props = { From 82e2f75f33a511830b7b4e7a41f0043fe988dc97 Mon Sep 17 00:00:00 2001 From: Thomas Brillard Date: Mon, 13 Jan 2025 14:20:44 +0100 Subject: [PATCH 6/7] chore: use a common click handler to avoid arrows in jsx --- .../components/TransactionConfirm/ConfirmFooter.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx b/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx index 85a0fa5a0457..93b8fd581c41 100644 --- a/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx +++ b/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx @@ -27,6 +27,8 @@ type Props = { manifestName?: string | null; }; +const handleUrlClick = (url?: string) => () => url && openURL(url); + const ConfirmFooter = ({ footer, transaction, manifestId, manifestName }: Props) => { if (!manifestId) return; const appNameByAddr = dexProvidersContractAddress[transaction?.recipient || ""]; @@ -47,7 +49,7 @@ const ConfirmFooter = ({ footer, transaction, manifestId, manifestName }: Props) components={[ openURL(termsOfUseUrl)} + onClick={handleUrlClick(termsOfUseUrl)} style={{ cursor: "pointer", textDecoration: "underline", @@ -55,7 +57,7 @@ const ConfirmFooter = ({ footer, transaction, manifestId, manifestName }: Props) />, openURL(privacyUrl)} + onClick={handleUrlClick(privacyUrl)} style={{ cursor: "pointer", textDecoration: "underline", From f3715a86dffd7f2aade8b264b8ea1fcc9ad613b4 Mon Sep 17 00:00:00 2001 From: Thomas Brillard Date: Mon, 13 Jan 2025 14:26:58 +0100 Subject: [PATCH 7/7] chore: use a common click handler to avoid arrows in jsx 2 --- .../renderer/components/TransactionConfirm/ConfirmFooter.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx b/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx index 93b8fd581c41..2bec780c6ebe 100644 --- a/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx +++ b/apps/ledger-live-desktop/src/renderer/components/TransactionConfirm/ConfirmFooter.tsx @@ -72,7 +72,7 @@ const ConfirmFooter = ({ footer, transaction, manifestId, manifestName }: Props) components={[ openURL(termsOfUseUrl)} + onClick={handleUrlClick(termsOfUseUrl)} style={{ cursor: "pointer", textDecoration: "underline",