From 46008464c58cc43a98681481c5b854e69004d2ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Von=C3=A1=C5=A1ek?= Date: Wed, 22 May 2024 16:44:19 +0200 Subject: [PATCH 01/23] Migration WIP --- src/components/AppProviders/AppProviders.tsx | 1 + src/sections/migration/MigrationProvider.tsx | 30 +++++++++++ .../migration/MigrationProvider.utils.ts | 35 ++++++++++++ .../migration/components/MigrationImport.tsx | 54 +++++++++++++++++++ .../migration/components/MigrationModal.tsx | 33 ++++++++++++ .../web3-connect/Web3Connect.utils.ts | 1 + 6 files changed, 154 insertions(+) create mode 100644 src/sections/migration/MigrationProvider.tsx create mode 100644 src/sections/migration/MigrationProvider.utils.ts create mode 100644 src/sections/migration/components/MigrationImport.tsx create mode 100644 src/sections/migration/components/MigrationModal.tsx diff --git a/src/components/AppProviders/AppProviders.tsx b/src/components/AppProviders/AppProviders.tsx index 547fdef41..32c5a6497 100644 --- a/src/components/AppProviders/AppProviders.tsx +++ b/src/components/AppProviders/AppProviders.tsx @@ -9,6 +9,7 @@ import { theme } from "theme" import * as React from "react" import * as Apps from "@galacticcouncil/apps" import { createComponent } from "@lit-labs/react" +import { MigrationProvider } from "sections/migration/MigrationProvider" const AppsPersistenceProvider = createComponent({ tagName: "gc-database-provider", diff --git a/src/sections/migration/MigrationProvider.tsx b/src/sections/migration/MigrationProvider.tsx new file mode 100644 index 000000000..59396d1d9 --- /dev/null +++ b/src/sections/migration/MigrationProvider.tsx @@ -0,0 +1,30 @@ +import { FC, PropsWithChildren } from "react" +import { useLocation } from "react-use" +import { MigrationModal } from "./components/MigrationModal" +import { MigrationImport } from "./components/MigrationImport" + +import { + MIGRATION_TRIGGER_URLS, + MIGRATION_TARGET_URL, + MIGRATION_QUERY_PARAM, +} from "sections/migration/MigrationProvider.utils" + +export const MigrationProvider: FC = ({ children }) => { + const { origin, search } = useLocation() + + const urlParams = new URLSearchParams(search) + + const shouldImport = + MIGRATION_TARGET_URL === origin && urlParams.has(MIGRATION_QUERY_PARAM) + const shouldMigrate = origin ? MIGRATION_TRIGGER_URLS.includes(origin) : false + + if (shouldImport) { + return + } + + if (shouldMigrate) { + return + } + + return <>{children} +} diff --git a/src/sections/migration/MigrationProvider.utils.ts b/src/sections/migration/MigrationProvider.utils.ts new file mode 100644 index 000000000..bcad37978 --- /dev/null +++ b/src/sections/migration/MigrationProvider.utils.ts @@ -0,0 +1,35 @@ +import { Buffer } from "buffer" + +export const MIGRATION_CHECK_KEY = "__migration-completed" +export const MIGRATION_QUERY_PARAM = "migration" +export const MIGRATION_TARGET_URL = "http://localhost:3001" +export const MIGRATION_TRIGGER_URLS = [ + "http://localhost:5173", + "https://app.hydradx.io", +] + +export const serializeLocalStorage = (keys: string[]): string => { + const data: { [key: string]: any } = {} + + keys.forEach((key) => { + const value = localStorage.getItem(key) + if (value) { + data[key] = JSON.parse(value) + } + }) + + const json = JSON.stringify(data) + return Buffer.from(json, "binary").toString("base64") +} + +export const importToLocalStorage = (data: string) => { + const json = Buffer.from(data, "base64").toString("binary") + const ls = JSON.parse(json) + + const keys = Object.keys(ls) + + keys.forEach((key) => { + const value = ls[key] + localStorage.setItem(key, JSON.stringify(value)) + }) +} diff --git a/src/sections/migration/components/MigrationImport.tsx b/src/sections/migration/components/MigrationImport.tsx new file mode 100644 index 000000000..e01cd8fdb --- /dev/null +++ b/src/sections/migration/components/MigrationImport.tsx @@ -0,0 +1,54 @@ +import { FC, useEffect, useState } from "react" +import { Button } from "components/Button/Button" +import { Modal } from "components/Modal/Modal" +import { Text } from "components/Typography/Text/Text" +import { + MIGRATION_CHECK_KEY, + importToLocalStorage, +} from "sections/migration/MigrationProvider.utils" + +export const MigrationImport: FC<{ data: string }> = ({ data }) => { + const [lastImportDate, setLastImportDate] = useState(null) + const handleImport = (data: string) => { + if (data) { + importToLocalStorage(data) + window.location.href = window.location.origin + localStorage.setItem(MIGRATION_CHECK_KEY, new Date().toISOString()) + } + } + + useEffect(() => { + const migrationStatus = localStorage.getItem(MIGRATION_CHECK_KEY) + const migrationCompletedOn = migrationStatus + ? new Date(migrationStatus) + : null + + if (migrationCompletedOn) { + setLastImportDate(new Date(migrationCompletedOn)) + } else { + handleImport(data) + } + }, [data]) + + if (!lastImportDate) { + return null + } + + return ( + + + You already migrated your settings on {lastImportDate.toLocaleString()}. + Do you want to overwrite your current settings? + + + + + ) +} diff --git a/src/sections/migration/components/MigrationModal.tsx b/src/sections/migration/components/MigrationModal.tsx new file mode 100644 index 000000000..64e6f2f95 --- /dev/null +++ b/src/sections/migration/components/MigrationModal.tsx @@ -0,0 +1,33 @@ +import { Button } from "components/Button/Button" +import { Modal } from "components/Modal/Modal" +import { Text } from "components/Typography/Text/Text" +import { + MIGRATION_QUERY_PARAM, + MIGRATION_TARGET_URL, + serializeLocalStorage, +} from "sections/migration/MigrationProvider.utils" + +export const MigrationModal = () => { + const data = serializeLocalStorage(["external-tokens", "address-book"]) + const url = `${MIGRATION_TARGET_URL}?${MIGRATION_QUERY_PARAM}=${data}` + + console.log({ url }) + + return ( + + + HydraDX is migrating to new domain. Click the button below to transfer + your settings. + + + + + ) +} diff --git a/src/sections/web3-connect/Web3Connect.utils.ts b/src/sections/web3-connect/Web3Connect.utils.ts index 35eb45e38..ef01d5a38 100644 --- a/src/sections/web3-connect/Web3Connect.utils.ts +++ b/src/sections/web3-connect/Web3Connect.utils.ts @@ -66,6 +66,7 @@ export const useEvmAccount = () => { ? await wallet?.extension?.request({ method: "eth_chainId" }) : null + console.log({ chainId }) return { chainId: Number(chainId), } From 848cbf635128d759b7a617bd014048833090fc7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Von=C3=A1=C5=A1ek?= Date: Thu, 23 May 2024 12:00:08 +0200 Subject: [PATCH 02/23] Migration WIP --- src/components/AppProviders/AppProviders.tsx | 34 ++++++++++--------- src/sections/migration/MigrationProvider.tsx | 20 +++++++---- .../migration/MigrationProvider.utils.ts | 8 ++--- ...tionModal.tsx => MigrationExportModal.tsx} | 11 ++---- ...ionImport.tsx => MigrationImportModal.tsx} | 33 ++++++++++++------ 5 files changed, 59 insertions(+), 47 deletions(-) rename src/sections/migration/components/{MigrationModal.tsx => MigrationExportModal.tsx} (70%) rename src/sections/migration/components/{MigrationImport.tsx => MigrationImportModal.tsx} (63%) diff --git a/src/components/AppProviders/AppProviders.tsx b/src/components/AppProviders/AppProviders.tsx index 32c5a6497..cb9f571cf 100644 --- a/src/components/AppProviders/AppProviders.tsx +++ b/src/components/AppProviders/AppProviders.tsx @@ -19,21 +19,23 @@ const AppsPersistenceProvider = createComponent({ export const AppProviders: FC = ({ children }) => { return ( - - - - - - {children} - - - - - - + + + + + + + {children} + + + + + + + ) } diff --git a/src/sections/migration/MigrationProvider.tsx b/src/sections/migration/MigrationProvider.tsx index 59396d1d9..636c035af 100644 --- a/src/sections/migration/MigrationProvider.tsx +++ b/src/sections/migration/MigrationProvider.tsx @@ -1,12 +1,14 @@ import { FC, PropsWithChildren } from "react" import { useLocation } from "react-use" -import { MigrationModal } from "./components/MigrationModal" -import { MigrationImport } from "./components/MigrationImport" +import { MigrationExportModal } from "./components/MigrationExportModal" +import { MigrationImportModal } from "./components/MigrationImportModal" import { - MIGRATION_TRIGGER_URLS, + MIGRATION_TRIGGER_URL, MIGRATION_TARGET_URL, MIGRATION_QUERY_PARAM, + MIGRATION_LS_KEYS, + serializeLocalStorage, } from "sections/migration/MigrationProvider.utils" export const MigrationProvider: FC = ({ children }) => { @@ -14,16 +16,20 @@ export const MigrationProvider: FC = ({ children }) => { const urlParams = new URLSearchParams(search) + const shouldExport = MIGRATION_TRIGGER_URL === origin const shouldImport = MIGRATION_TARGET_URL === origin && urlParams.has(MIGRATION_QUERY_PARAM) - const shouldMigrate = origin ? MIGRATION_TRIGGER_URLS.includes(origin) : false if (shouldImport) { - return + return ( + + ) } - if (shouldMigrate) { - return + if (shouldExport) { + return ( + + ) } return <>{children} diff --git a/src/sections/migration/MigrationProvider.utils.ts b/src/sections/migration/MigrationProvider.utils.ts index bcad37978..c7bbf0b86 100644 --- a/src/sections/migration/MigrationProvider.utils.ts +++ b/src/sections/migration/MigrationProvider.utils.ts @@ -1,12 +1,10 @@ import { Buffer } from "buffer" +export const MIGRATION_LS_KEYS = ["external-tokens", "address-book"] export const MIGRATION_CHECK_KEY = "__migration-completed" export const MIGRATION_QUERY_PARAM = "migration" -export const MIGRATION_TARGET_URL = "http://localhost:3001" -export const MIGRATION_TRIGGER_URLS = [ - "http://localhost:5173", - "https://app.hydradx.io", -] +export const MIGRATION_TARGET_URL = "http://localhost:5173" +export const MIGRATION_TRIGGER_URL = "http://localhost:5173" export const serializeLocalStorage = (keys: string[]): string => { const data: { [key: string]: any } = {} diff --git a/src/sections/migration/components/MigrationModal.tsx b/src/sections/migration/components/MigrationExportModal.tsx similarity index 70% rename from src/sections/migration/components/MigrationModal.tsx rename to src/sections/migration/components/MigrationExportModal.tsx index 64e6f2f95..9df54a4ae 100644 --- a/src/sections/migration/components/MigrationModal.tsx +++ b/src/sections/migration/components/MigrationExportModal.tsx @@ -1,18 +1,13 @@ +import { FC } from "react" import { Button } from "components/Button/Button" import { Modal } from "components/Modal/Modal" import { Text } from "components/Typography/Text/Text" import { MIGRATION_QUERY_PARAM, MIGRATION_TARGET_URL, - serializeLocalStorage, } from "sections/migration/MigrationProvider.utils" -export const MigrationModal = () => { - const data = serializeLocalStorage(["external-tokens", "address-book"]) - const url = `${MIGRATION_TARGET_URL}?${MIGRATION_QUERY_PARAM}=${data}` - - console.log({ url }) - +export const MigrationExportModal: FC<{ data: string }> = ({ data }) => { return ( @@ -23,7 +18,7 @@ export const MigrationModal = () => { +
+ + +
) } From 3d447cbdaedec998e71b991eca763e2ca0631943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Von=C3=A1=C5=A1ek?= Date: Thu, 23 May 2024 12:01:59 +0200 Subject: [PATCH 03/23] removed debug --- src/sections/web3-connect/Web3Connect.utils.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sections/web3-connect/Web3Connect.utils.ts b/src/sections/web3-connect/Web3Connect.utils.ts index ef01d5a38..35eb45e38 100644 --- a/src/sections/web3-connect/Web3Connect.utils.ts +++ b/src/sections/web3-connect/Web3Connect.utils.ts @@ -66,7 +66,6 @@ export const useEvmAccount = () => { ? await wallet?.extension?.request({ method: "eth_chainId" }) : null - console.log({ chainId }) return { chainId: Number(chainId), } From 94e5f4f4c46c967582152359fe00fdc17a45837a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Von=C3=A1=C5=A1ek?= Date: Thu, 23 May 2024 12:05:55 +0200 Subject: [PATCH 04/23] update trigger/target urls --- src/sections/migration/MigrationProvider.utils.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/sections/migration/MigrationProvider.utils.ts b/src/sections/migration/MigrationProvider.utils.ts index c7bbf0b86..d4799df59 100644 --- a/src/sections/migration/MigrationProvider.utils.ts +++ b/src/sections/migration/MigrationProvider.utils.ts @@ -3,8 +3,10 @@ import { Buffer } from "buffer" export const MIGRATION_LS_KEYS = ["external-tokens", "address-book"] export const MIGRATION_CHECK_KEY = "__migration-completed" export const MIGRATION_QUERY_PARAM = "migration" -export const MIGRATION_TARGET_URL = "http://localhost:5173" -export const MIGRATION_TRIGGER_URL = "http://localhost:5173" +export const MIGRATION_TRIGGER_URL = + "https://deploy-preview-1333--testnet-hydra-app.netlify.app" +export const MIGRATION_TARGET_URL = + "https://deploy-preview-1334--testnet-hydra-app.netlify.app" export const serializeLocalStorage = (keys: string[]): string => { const data: { [key: string]: any } = {} From dbb810758925efaa69546318e85a9e4e3a33d4c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Von=C3=A1=C5=A1ek?= Date: Thu, 23 May 2024 13:01:19 +0200 Subject: [PATCH 05/23] added more LS keys --- src/sections/migration/MigrationProvider.utils.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/sections/migration/MigrationProvider.utils.ts b/src/sections/migration/MigrationProvider.utils.ts index d4799df59..1e3d7645c 100644 --- a/src/sections/migration/MigrationProvider.utils.ts +++ b/src/sections/migration/MigrationProvider.utils.ts @@ -1,6 +1,11 @@ import { Buffer } from "buffer" -export const MIGRATION_LS_KEYS = ["external-tokens", "address-book"] +export const MIGRATION_LS_KEYS = [ + "external-tokens", + "address-book", + "toasts", + "hydradx-rpc-list", +] export const MIGRATION_CHECK_KEY = "__migration-completed" export const MIGRATION_QUERY_PARAM = "migration" export const MIGRATION_TRIGGER_URL = From 08caad50c23c3bdc36fdb70be389d233653a660a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Von=C3=A1=C5=A1ek?= Date: Thu, 23 May 2024 13:11:19 +0200 Subject: [PATCH 06/23] added more LS keys --- src/sections/migration/MigrationProvider.utils.ts | 2 ++ src/sections/migration/components/MigrationImportModal.tsx | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/sections/migration/MigrationProvider.utils.ts b/src/sections/migration/MigrationProvider.utils.ts index 1e3d7645c..0b962311d 100644 --- a/src/sections/migration/MigrationProvider.utils.ts +++ b/src/sections/migration/MigrationProvider.utils.ts @@ -4,7 +4,9 @@ export const MIGRATION_LS_KEYS = [ "external-tokens", "address-book", "toasts", + "rpcUrl", "hydradx-rpc-list", + "referral-codes", ] export const MIGRATION_CHECK_KEY = "__migration-completed" export const MIGRATION_QUERY_PARAM = "migration" diff --git a/src/sections/migration/components/MigrationImportModal.tsx b/src/sections/migration/components/MigrationImportModal.tsx index d00441f9e..4e66afbc6 100644 --- a/src/sections/migration/components/MigrationImportModal.tsx +++ b/src/sections/migration/components/MigrationImportModal.tsx @@ -46,7 +46,7 @@ export const MigrationImportModal: FC<{ data: string }> = ({ data }) => { + {t("migration.export.question")} + + +
+ + + +
) } diff --git a/src/sections/migration/components/MigrationImportModal.tsx b/src/sections/migration/components/MigrationImportModal.tsx index 0b2204332..a40818b46 100644 --- a/src/sections/migration/components/MigrationImportModal.tsx +++ b/src/sections/migration/components/MigrationImportModal.tsx @@ -1,33 +1,39 @@ -import { FC, useEffect, useState } from "react" import { Button } from "components/Button/Button" import { Modal } from "components/Modal/Modal" +import { Separator } from "components/Separator/Separator" import { Text } from "components/Typography/Text/Text" +import { FC, useEffect, useState } from "react" +import { useTranslation } from "react-i18next" import { MIGRATION_CHECK_KEY, importToLocalStorage, } from "sections/migration/MigrationProvider.utils" +import MigrationLogo from "assets/icons/migration/MigrationLogo.svg?react" + +const reloadAppWithTimestamp = (ts: string) => { + window.location.href = window.location.origin + localStorage.setItem(MIGRATION_CHECK_KEY, ts || "0") +} -export const MigrationImportModal: FC<{ data: string }> = ({ data }) => { +export const MigrationImportModal: FC<{ data?: string }> = ({ data }) => { + const { t } = useTranslation() const [lastImportDate, setLastImportDate] = useState(null) - const handleImport = (data: string) => { - if (data) { - importToLocalStorage(data) - localStorage.setItem(MIGRATION_CHECK_KEY, new Date().toISOString()) - window.location.href = window.location.origin - } - } useEffect(() => { const migrationStatus = localStorage.getItem(MIGRATION_CHECK_KEY) - const migrationCompletedOn = migrationStatus - ? new Date(migrationStatus) - : null + const migrationCompletedOn = + migrationStatus && migrationStatus !== "0" + ? new Date(migrationStatus) + : null - if (migrationCompletedOn) { + if (migrationCompletedOn && !!data) { setLastImportDate(new Date(migrationCompletedOn)) - } else { - handleImport(data) + return + } else if (!!data) { + importToLocalStorage(data) } + + reloadAppWithTimestamp(data ? new Date().toISOString() : "0") }, [data]) if (!lastImportDate) { @@ -35,30 +41,41 @@ export const MigrationImportModal: FC<{ data: string }> = ({ data }) => { } return ( - - - You already transferred your settings on{" "} - {lastImportDate.toLocaleString()}. Do you want to overwrite your current - settings? + + + + {t("migration.import.title")} - -
+ + {t("migration.import.description", { date: lastImportDate })} + + +
- + {data && ( + + )}
) From 854b071458bfb46ed708be2102118fe88a781f37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Von=C3=A1=C5=A1ek?= Date: Wed, 29 May 2024 22:48:43 +0200 Subject: [PATCH 10/23] update param key --- src/sections/migration/MigrationProvider.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sections/migration/MigrationProvider.tsx b/src/sections/migration/MigrationProvider.tsx index 48d178382..36dae7340 100644 --- a/src/sections/migration/MigrationProvider.tsx +++ b/src/sections/migration/MigrationProvider.tsx @@ -14,12 +14,12 @@ import { export const MigrationProvider: FC = ({ children }) => { const { origin, search } = useLocation() - const data = search?.replace(`?${MIGRATION_QUERY_PARAM}=`, "") ?? "" + const paramKey = `?${MIGRATION_QUERY_PARAM}=` + const data = search?.replace(paramKey, "") ?? "" const shouldExport = MIGRATION_TRIGGER_URL === origin const shouldImport = - MIGRATION_TARGET_URL === origin && - search?.startsWith(`?${MIGRATION_QUERY_PARAM}`) + MIGRATION_TARGET_URL === origin && search?.startsWith(paramKey) if (shouldImport) { return From 720b4ae9574deece588b4f80c7c6132bdf541176 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Von=C3=A1=C5=A1ek?= Date: Thu, 30 May 2024 20:50:19 +0200 Subject: [PATCH 11/23] Allow user to cancel migration and stay on old domain --- src/sections/migration/MigrationProvider.tsx | 17 ++++++++++++++--- .../migration/MigrationProvider.utils.ts | 3 ++- .../components/MigrationExportModal.tsx | 13 +++++-------- .../components/MigrationImportModal.tsx | 6 +++--- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/sections/migration/MigrationProvider.tsx b/src/sections/migration/MigrationProvider.tsx index 36dae7340..877d80143 100644 --- a/src/sections/migration/MigrationProvider.tsx +++ b/src/sections/migration/MigrationProvider.tsx @@ -1,4 +1,4 @@ -import { FC, PropsWithChildren } from "react" +import { FC, PropsWithChildren, useState } from "react" import { useLocation } from "react-use" import { MigrationExportModal } from "./components/MigrationExportModal" import { MigrationImportModal } from "./components/MigrationImportModal" @@ -9,11 +9,16 @@ import { MIGRATION_QUERY_PARAM, MIGRATION_LS_KEYS, serializeLocalStorage, + MIGRATION_CANCELED_FLAG, } from "sections/migration/MigrationProvider.utils" export const MigrationProvider: FC = ({ children }) => { const { origin, search } = useLocation() + const [migrationCanceled, setMigrationCanceled] = useState( + localStorage.getItem(MIGRATION_CANCELED_FLAG) === "true", + ) + const paramKey = `?${MIGRATION_QUERY_PARAM}=` const data = search?.replace(paramKey, "") ?? "" @@ -25,9 +30,15 @@ export const MigrationProvider: FC = ({ children }) => { return } - if (shouldExport) { + if (shouldExport && !migrationCanceled) { return ( - + { + localStorage.setItem(MIGRATION_CANCELED_FLAG, "true") + setMigrationCanceled(true) + }} + /> ) } diff --git a/src/sections/migration/MigrationProvider.utils.ts b/src/sections/migration/MigrationProvider.utils.ts index 31d6d4c5b..2915a747c 100644 --- a/src/sections/migration/MigrationProvider.utils.ts +++ b/src/sections/migration/MigrationProvider.utils.ts @@ -10,7 +10,8 @@ export const MIGRATION_LS_KEYS = [ "dca.settings", "trade.settings", ] -export const MIGRATION_CHECK_KEY = "__migration-completed" +export const MIGRATION_COMPLETE_FLAG = "__migration-completed" +export const MIGRATION_CANCELED_FLAG = "__migration-canceled" export const MIGRATION_QUERY_PARAM = "migration" export const MIGRATION_TRIGGER_URL = "https://deploy-preview-1333--testnet-hydra-app.netlify.app" diff --git a/src/sections/migration/components/MigrationExportModal.tsx b/src/sections/migration/components/MigrationExportModal.tsx index 4fe7c2648..058309514 100644 --- a/src/sections/migration/components/MigrationExportModal.tsx +++ b/src/sections/migration/components/MigrationExportModal.tsx @@ -10,7 +10,10 @@ import MigrationLogo from "assets/icons/migration/MigrationLogo.svg?react" import { useTranslation } from "react-i18next" import { Separator } from "components/Separator/Separator" -export const MigrationExportModal: FC<{ data: string }> = ({ data }) => { +export const MigrationExportModal: FC<{ + data: string + onCancel: () => void +}> = ({ data, onCancel }) => { const { t } = useTranslation() return ( @@ -37,13 +40,7 @@ export const MigrationExportModal: FC<{ data: string }> = ({ data }) => { color="darkBlue401" />
- +