From 24e8c4561b14bb00954bbe43a1fdd40ecf291dd5 Mon Sep 17 00:00:00 2001 From: Jakub Date: Thu, 17 Oct 2024 00:29:07 +0200 Subject: [PATCH 01/51] Set user id for Sentry scope To be able to track user events in Sentry, we need to set the user id in the scope. --- dapp/src/sentry/index.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dapp/src/sentry/index.ts b/dapp/src/sentry/index.ts index ea82f8be0..548423fd5 100644 --- a/dapp/src/sentry/index.ts +++ b/dapp/src/sentry/index.ts @@ -9,10 +9,15 @@ const initialize = (dsn: string) => { }) } +const setUser = (bitcoinAddress: string | undefined) => { + Sentry.setUser(bitcoinAddress ? { id: bitcoinAddress } : null) +} + const captureException = (exception: unknown) => Sentry.captureException(exception) export default { initialize, + setUser, captureException, } From 2fc6d8b492d20183dc0bc2be29d2d34573abf2f1 Mon Sep 17 00:00:00 2001 From: Jakub Date: Thu, 17 Oct 2024 00:30:01 +0200 Subject: [PATCH 02/51] Set user address when connecting and disconnecting wallet When the wallet is connected, the user address is set in the Sentry context. When the wallet is disconnected, the user address is cleared from the Sentry context. --- dapp/src/hooks/useWallet.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dapp/src/hooks/useWallet.ts b/dapp/src/hooks/useWallet.ts index 7cca52e6f..6435227f5 100644 --- a/dapp/src/hooks/useWallet.ts +++ b/dapp/src/hooks/useWallet.ts @@ -1,6 +1,7 @@ import { useCallback, useEffect, useMemo, useState } from "react" import { useAccount, useChainId, useConnect, useDisconnect } from "wagmi" import { logPromiseFailure, orangeKit } from "#/utils" +import sentry from "#/sentry" import { OnErrorCallback, OrangeKitConnector, @@ -86,6 +87,7 @@ export function useWallet(): UseWalletReturn { { onSuccess: () => { resetWalletState() + sentry.setUser(undefined) }, }, ) @@ -97,6 +99,7 @@ export function useWallet(): UseWalletReturn { const btcAddress = await connector.getBitcoinAddress() setAddress(btcAddress) + sentry.setUser(btcAddress) } else { setAddress(undefined) } From 999d1b4a5204be82216d109c277b5496ecf380be Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Fri, 15 Nov 2024 12:35:32 +0100 Subject: [PATCH 03/51] Calculate points based on value after subtracting fees We are estimating points on the deposit form based on the deposit amount entered by the user. we think the points should be calculated on the value we estimate the deposit will have after fees subtraction (i.e. "You will deposit" amount). --- .../StakeFormModal/AcrePointsRewardEstimation.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/dapp/src/components/TransactionModal/ActiveStakingStep/StakeFormModal/AcrePointsRewardEstimation.tsx b/dapp/src/components/TransactionModal/ActiveStakingStep/StakeFormModal/AcrePointsRewardEstimation.tsx index 1ee18a2d8..81b7d54b2 100644 --- a/dapp/src/components/TransactionModal/ActiveStakingStep/StakeFormModal/AcrePointsRewardEstimation.tsx +++ b/dapp/src/components/TransactionModal/ActiveStakingStep/StakeFormModal/AcrePointsRewardEstimation.tsx @@ -13,7 +13,11 @@ import { H4, TextMd } from "#/components/shared/Typography" import { numberToLocaleString } from "#/utils" import { IconChevronDown } from "@tabler/icons-react" import { TOKEN_AMOUNT_FIELD_NAME } from "#/components/shared/TokenAmountForm/TokenAmountFormBase" -import { useFormField, useMinDepositAmount } from "#/hooks" +import { + useFormField, + useMinDepositAmount, + useTransactionDetails, +} from "#/hooks" import { ONE_MONTH_IN_DAYS, ONE_WEEK_IN_DAYS } from "#/constants" const ACRE_POINTS_DATA = { @@ -48,8 +52,9 @@ function AcrePointsRewardEstimation(props: StackProps) { const { value = 0n } = useFormField( TOKEN_AMOUNT_FIELD_NAME, ) + const { estimatedAmount } = useTransactionDetails(value) const minDepositAmount = useMinDepositAmount() - const amount = value >= minDepositAmount ? value : 0n + const amount = value >= minDepositAmount ? estimatedAmount : 0n const baseReward = Number(amount) const pointsRate = 10000 From fdd748ff49dde1c81e2dd3ab5a384fcb30f3e65b Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Mon, 18 Nov 2024 16:32:22 +0100 Subject: [PATCH 04/51] Round down the number of points --- .../StakeFormModal/AcrePointsRewardEstimation.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dapp/src/components/TransactionModal/ActiveStakingStep/StakeFormModal/AcrePointsRewardEstimation.tsx b/dapp/src/components/TransactionModal/ActiveStakingStep/StakeFormModal/AcrePointsRewardEstimation.tsx index 81b7d54b2..242664a3d 100644 --- a/dapp/src/components/TransactionModal/ActiveStakingStep/StakeFormModal/AcrePointsRewardEstimation.tsx +++ b/dapp/src/components/TransactionModal/ActiveStakingStep/StakeFormModal/AcrePointsRewardEstimation.tsx @@ -60,7 +60,7 @@ function AcrePointsRewardEstimation(props: StackProps) { const pointsRate = 10000 const estimatedReward = useMemo( - () => (selectedTierItem.multipler * baseReward) / pointsRate, + () => Math.floor((selectedTierItem.multipler * baseReward) / pointsRate), [baseReward, selectedTierItem], ) From d1bb7430c5244b331dedb1eb939ed19419127cd5 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 20 Nov 2024 10:43:25 +0100 Subject: [PATCH 05/51] Enable mobile mode for Ledger Live --- dapp/src/components/Layout.tsx | 4 ++-- dapp/src/hooks/useMobileMode.ts | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/dapp/src/components/Layout.tsx b/dapp/src/components/Layout.tsx index ea34096aa..7e3f491d2 100644 --- a/dapp/src/components/Layout.tsx +++ b/dapp/src/components/Layout.tsx @@ -18,9 +18,9 @@ const PAGE_MAX_WIDTH: Record = { function Layout() { const isMobileMode = useMobileMode() - const { embeddedApp } = useIsEmbed() + const { isEmbed, embeddedApp } = useIsEmbed() - if (isMobileMode) return + if (!isEmbed && isMobileMode) return const maxWidth = embeddedApp ? PAGE_MAX_WIDTH[embeddedApp] diff --git a/dapp/src/hooks/useMobileMode.ts b/dapp/src/hooks/useMobileMode.ts index 25a491c1d..07e7de6a1 100644 --- a/dapp/src/hooks/useMobileMode.ts +++ b/dapp/src/hooks/useMobileMode.ts @@ -2,13 +2,11 @@ import { screen } from "#/constants" import { userAgent as userAgentUtils } from "#/utils" import { useMediaQuery } from "@chakra-ui/react" import { useMemo } from "react" -import useIsEmbed from "./useIsEmbed" const { MAX_MOBILE_SCREEN_WIDTH } = screen const { getDeviceDetect } = userAgentUtils const useMobileMode = () => { - const { isEmbed } = useIsEmbed() const [isMobileScreen] = useMediaQuery( `(max-width: ${MAX_MOBILE_SCREEN_WIDTH})`, ) @@ -30,7 +28,7 @@ const useMobileMode = () => { return isMobileDevice() }, [isMobileScreen]) - return !isEmbed && isMobile + return isMobile } export default useMobileMode From af1165edc8f51ec4441ed397a9e59e3953ab8f87 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 20 Nov 2024 15:37:57 +0100 Subject: [PATCH 06/51] Optimize dApp layout for Ledger Live Mobile --- dapp/src/components/ArrivingSoonTooltip.tsx | 4 +- .../ConnectWalletErrorAlert.tsx | 2 +- .../ConnectWalletStatusLabel.tsx | 4 +- dapp/src/components/Footer.tsx | 4 ++ .../src/components/TransactionModal/index.tsx | 7 --- dapp/src/components/WelcomeModal.tsx | 31 +++++++------ dapp/src/constants/screen.ts | 2 +- .../pages/DashboardPage/AcreTVLProgress.tsx | 4 +- .../pages/DashboardPage/PositionDetails.tsx | 38 +++++++++++---- .../TransactionHistory/TransactionTable.tsx | 5 +- dapp/src/pages/DashboardPage/index.tsx | 46 +++++++++++-------- dapp/src/theme/AcreTVLProgress.ts | 4 +- 12 files changed, 93 insertions(+), 58 deletions(-) diff --git a/dapp/src/components/ArrivingSoonTooltip.tsx b/dapp/src/components/ArrivingSoonTooltip.tsx index e5ce8701c..f8d2c2b01 100644 --- a/dapp/src/components/ArrivingSoonTooltip.tsx +++ b/dapp/src/components/ArrivingSoonTooltip.tsx @@ -2,14 +2,16 @@ import React, { ReactNode } from "react" import { Tooltip } from "@chakra-ui/react" export default function ArrivingSoonTooltip({ + label, shouldDisplayTooltip, children, }: { + label?: string shouldDisplayTooltip: boolean children: ReactNode }) { return shouldDisplayTooltip ? ( - {children} + {children} ) : ( children ) diff --git a/dapp/src/components/ConnectWalletModal/ConnectWalletErrorAlert.tsx b/dapp/src/components/ConnectWalletModal/ConnectWalletErrorAlert.tsx index e7439d8e4..2e97b59ea 100644 --- a/dapp/src/components/ConnectWalletModal/ConnectWalletErrorAlert.tsx +++ b/dapp/src/components/ConnectWalletModal/ConnectWalletErrorAlert.tsx @@ -39,7 +39,7 @@ export default function ConnectWalletErrorAlert( - {title} + {title} {description} diff --git a/dapp/src/components/ConnectWalletModal/ConnectWalletStatusLabel.tsx b/dapp/src/components/ConnectWalletModal/ConnectWalletStatusLabel.tsx index 5f89720f8..ec1a0e651 100644 --- a/dapp/src/components/ConnectWalletModal/ConnectWalletStatusLabel.tsx +++ b/dapp/src/components/ConnectWalletModal/ConnectWalletStatusLabel.tsx @@ -46,12 +46,12 @@ export default function ConnectWalletStatusLabel({ return ( - + {icon} {label} {isError && ( - + Rejected by user diff --git a/dapp/src/components/Footer.tsx b/dapp/src/components/Footer.tsx index 7a907a5c5..d80161d7f 100644 --- a/dapp/src/components/Footer.tsx +++ b/dapp/src/components/Footer.tsx @@ -11,6 +11,7 @@ import { } from "@chakra-ui/react" import { EXTERNAL_HREF } from "#/constants" import { AcreSignIcon, ArrowUpRight } from "#/assets/icons" +import { useMobileMode } from "#/hooks" type FooterListItem = Pick @@ -74,6 +75,9 @@ const getItemsList = ( export default function Footer() { const styles = useMultiStyleConfig("Footer") + const isMobileMode = useMobileMode() + + if (isMobileMode) return null return ( diff --git a/dapp/src/components/TransactionModal/index.tsx b/dapp/src/components/TransactionModal/index.tsx index 68add35cc..dd30a73ad 100644 --- a/dapp/src/components/TransactionModal/index.tsx +++ b/dapp/src/components/TransactionModal/index.tsx @@ -4,7 +4,6 @@ import { useAppDispatch, useFetchActivities, useIsSignedMessage, - useSidebar, useTransactionModal, } from "#/hooks" import { ActionFlowType, BaseModalProps } from "#/types" @@ -18,7 +17,6 @@ import { ConnectWalletModalBase } from "../ConnectWalletModal" type TransactionModalProps = { type: ActionFlowType } & BaseModalProps function TransactionModalBase({ type, closeModal }: TransactionModalProps) { - const { onOpen: openSideBar, onClose: closeSidebar } = useSidebar() const dispatch = useAppDispatch() const fetchActivities = useFetchActivities() @@ -34,11 +32,6 @@ function TransactionModalBase({ type, closeModal }: TransactionModalProps) { } }, [dispatch, fetchActivities]) - useEffect(() => { - openSideBar() - return () => closeSidebar() - }, [closeSidebar, openSideBar]) - return ( diff --git a/dapp/src/components/WelcomeModal.tsx b/dapp/src/components/WelcomeModal.tsx index d40d0bc75..a2666955b 100644 --- a/dapp/src/components/WelcomeModal.tsx +++ b/dapp/src/components/WelcomeModal.tsx @@ -17,7 +17,7 @@ import { import { H3, TextSm } from "#/components/shared/Typography" import { BaseModalProps, DappMode } from "#/types" import { EmbedApp } from "#/utils/referralProgram" -import { useIsEmbed } from "#/hooks" +import { useIsEmbed, useMobileMode } from "#/hooks" import withBaseModal from "./ModalRoot/withBaseModal" import step1Video from "../assets/videos/welcome-steps/welcome-step-1.mp4" import step2Video from "../assets/videos/welcome-steps/welcome-step-2.mp4" @@ -122,6 +122,7 @@ function WelcomeModalBase({ closeModal }: BaseModalProps) { count: steps.length, }) as UseStepsReturn & { goToNext: () => void } const { embeddedApp } = useIsEmbed() + const isMobileMode = useMobileMode() const isLastStep = activeStep + 1 === steps.length const activeStepData = steps[activeStep] @@ -159,19 +160,21 @@ function WelcomeModalBase({ closeModal }: BaseModalProps) { - + {!isMobileMode && ( + + )} ) } diff --git a/dapp/src/constants/screen.ts b/dapp/src/constants/screen.ts index 70538bd61..c57950789 100644 --- a/dapp/src/constants/screen.ts +++ b/dapp/src/constants/screen.ts @@ -1,3 +1,3 @@ -const MAX_MOBILE_SCREEN_WIDTH = "1023px" +const MAX_MOBILE_SCREEN_WIDTH = "600px" export default { MAX_MOBILE_SCREEN_WIDTH } diff --git a/dapp/src/pages/DashboardPage/AcreTVLProgress.tsx b/dapp/src/pages/DashboardPage/AcreTVLProgress.tsx index d9b8078ab..51c645153 100644 --- a/dapp/src/pages/DashboardPage/AcreTVLProgress.tsx +++ b/dapp/src/pages/DashboardPage/AcreTVLProgress.tsx @@ -33,7 +33,7 @@ export function AcreTVLProgress(props: AcreTVLProgressProps) { return ( - + @@ -59,7 +59,7 @@ export function AcreTVLProgress(props: AcreTVLProgressProps) { 2} /> - + ) } diff --git a/dapp/src/pages/DashboardPage/PositionDetails.tsx b/dapp/src/pages/DashboardPage/PositionDetails.tsx index c05c6163a..77b55cd5e 100644 --- a/dapp/src/pages/DashboardPage/PositionDetails.tsx +++ b/dapp/src/pages/DashboardPage/PositionDetails.tsx @@ -6,6 +6,7 @@ import { useTransactionModal, useStatistics, useWallet, + useMobileMode, } from "#/hooks" import { ACTION_FLOW_TYPES } from "#/types" import { @@ -41,6 +42,10 @@ export default function PositionDetails() { const openDepositModal = useTransactionModal(ACTION_FLOW_TYPES.STAKE) const openWithdrawModal = useTransactionModal(ACTION_FLOW_TYPES.UNSTAKE) const activitiesCount = useAllActivitiesCount() + const isMobileMode = useMobileMode() + const arrivingSoonLabel = isMobileMode + ? "Arriving Soon to mobile devices" + : undefined const { tvl } = useStatistics() @@ -91,24 +96,39 @@ export default function PositionDetails() { - + + {isConnected && activitiesCount > 0 && ( - + diff --git a/dapp/src/pages/DashboardPage/TransactionHistory/TransactionTable.tsx b/dapp/src/pages/DashboardPage/TransactionHistory/TransactionTable.tsx index a29242694..b6ed02c49 100644 --- a/dapp/src/pages/DashboardPage/TransactionHistory/TransactionTable.tsx +++ b/dapp/src/pages/DashboardPage/TransactionHistory/TransactionTable.tsx @@ -13,7 +13,7 @@ import { displayBlockTimestamp, getActivityTimestamp } from "#/utils" import { Activity } from "#/types" import BlockExplorerLink from "#/components/shared/BlockExplorerLink" import { IconArrowUpRight } from "@tabler/icons-react" -import { useActivities } from "#/hooks" +import { useActivities, useMobileMode } from "#/hooks" import { semanticTokens } from "#/theme/utils" import EstimatedDuration from "./EstimatedDuration" @@ -21,9 +21,10 @@ const BLOCK_EXPLORER_CELL_MIN_WIDTH = 16 export default function TransactionTable() { const activities = useActivities() + const isMobileMode = useMobileMode() return ( - + {(pageData: Activity[]) => pageData.map((activity) => ( diff --git a/dapp/src/pages/DashboardPage/index.tsx b/dapp/src/pages/DashboardPage/index.tsx index 6f28092ec..f2be13b21 100644 --- a/dapp/src/pages/DashboardPage/index.tsx +++ b/dapp/src/pages/DashboardPage/index.tsx @@ -9,28 +9,38 @@ import AcrePointsTemplateCard from "./AcrePointsTemplateCard" import BeehiveCard from "./BeehiveCard" import { AcreTVLProgress } from "./AcreTVLProgress" -const TEMPLATE_AREAS = ` - ${featureFlags.TVL_ENABLED ? '"tvl tvl"' : ""} - "dashboard acre-points" - "dashboard beehive" - "dashboard useful-links" -` - -const GRID_TEMPLATE_ROWS = `${featureFlags.TVL_ENABLED ? "auto" : ""} auto auto 1fr` - export default function DashboardPage() { useTriggerConnectWalletModal() return ( {featureFlags.TVL_ENABLED && } @@ -40,12 +50,12 @@ export default function DashboardPage() { {/* */} {featureFlags.ACRE_POINTS_ENABLED ? ( - + ) : ( - + )} - + ) } diff --git a/dapp/src/theme/AcreTVLProgress.ts b/dapp/src/theme/AcreTVLProgress.ts index 622b34263..640b8b6eb 100644 --- a/dapp/src/theme/AcreTVLProgress.ts +++ b/dapp/src/theme/AcreTVLProgress.ts @@ -27,7 +27,9 @@ const containerStyles = defineStyle({ const wrapperStyles = defineStyle({ px: 5, py: 6, - gap: "6.875rem", // 110px + display: "flex", + flexDirection: { base: "column", sm: "row" }, // 110px + gap: { base: 5, md: "6.875rem" }, // 110px }) const contentWrapperStyles = defineStyle({ gridAutoFlow: "column", From b0e7deaeae0e182c5ca99c91d4ae283e2d8f1e70 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 20 Nov 2024 15:40:46 +0100 Subject: [PATCH 07/51] Change "Staking" to "Acre App" --- dapp/src/components/MobileModeBanner/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dapp/src/components/MobileModeBanner/index.tsx b/dapp/src/components/MobileModeBanner/index.tsx index e8a0028b4..672a11ef8 100644 --- a/dapp/src/components/MobileModeBanner/index.tsx +++ b/dapp/src/components/MobileModeBanner/index.tsx @@ -46,7 +46,7 @@ function MobileModeBanner(props: MobileModeBannerProps) { > - Staking is on + Acre app is on desktop! @@ -92,7 +92,7 @@ function MobileModeBanner(props: MobileModeBannerProps) {

- Staking is live only on desktop for now. We're working with + Acre app live only on desktop for now. We're working with partners to bring it to mobile soon.

From d235954bf4bc16a32c2e3717359c705b59b9b82a Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 20 Nov 2024 15:46:57 +0100 Subject: [PATCH 08/51] Fix styles for beehive component --- dapp/src/pages/DashboardPage/BeehiveCard.tsx | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/dapp/src/pages/DashboardPage/BeehiveCard.tsx b/dapp/src/pages/DashboardPage/BeehiveCard.tsx index bba103729..c252c6762 100644 --- a/dapp/src/pages/DashboardPage/BeehiveCard.tsx +++ b/dapp/src/pages/DashboardPage/BeehiveCard.tsx @@ -42,14 +42,12 @@ export default function BeehiveCard(props: CardProps) { - - - - Total collected mats from Mezo - - - - + + + Total collected mats from Mezo + + + {data && (
{numberToLocaleString(data.totalMats)} From 403911e69a102bfc3728af6e2bbceff2b3bb0d02 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 20 Nov 2024 16:08:25 +0100 Subject: [PATCH 09/51] Add support for tooltips on mobile mode --- dapp/src/components/ArrivingSoonTooltip.tsx | 2 +- dapp/src/components/Header/ConnectWallet.tsx | 2 +- .../shared/CurrencyBalance/index.tsx | 2 +- dapp/src/components/shared/InfoTooltip.tsx | 3 ++- dapp/src/components/shared/Tooltip.tsx | 19 +++++++++++++++++++ 5 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 dapp/src/components/shared/Tooltip.tsx diff --git a/dapp/src/components/ArrivingSoonTooltip.tsx b/dapp/src/components/ArrivingSoonTooltip.tsx index f8d2c2b01..24c87ceba 100644 --- a/dapp/src/components/ArrivingSoonTooltip.tsx +++ b/dapp/src/components/ArrivingSoonTooltip.tsx @@ -1,5 +1,5 @@ import React, { ReactNode } from "react" -import { Tooltip } from "@chakra-ui/react" +import Tooltip from "./shared/Tooltip" export default function ArrivingSoonTooltip({ label, diff --git a/dapp/src/components/Header/ConnectWallet.tsx b/dapp/src/components/Header/ConnectWallet.tsx index e3424ed1d..b1b598746 100644 --- a/dapp/src/components/Header/ConnectWallet.tsx +++ b/dapp/src/components/Header/ConnectWallet.tsx @@ -6,7 +6,6 @@ import { Icon, IconButton, StackDivider, - Tooltip, useClipboard, useMultiStyleConfig, } from "@chakra-ui/react" @@ -24,6 +23,7 @@ import { IconUserCode, } from "@tabler/icons-react" import { useMatch } from "react-router-dom" +import Tooltip from "../shared/Tooltip" function isChangeAccountFeatureSupported(embeddedApp: string | undefined) { return referralProgram.isEmbedApp(embeddedApp) diff --git a/dapp/src/components/shared/CurrencyBalance/index.tsx b/dapp/src/components/shared/CurrencyBalance/index.tsx index 87dede894..bf7f65750 100644 --- a/dapp/src/components/shared/CurrencyBalance/index.tsx +++ b/dapp/src/components/shared/CurrencyBalance/index.tsx @@ -4,7 +4,6 @@ import { useMultiStyleConfig, TextProps, ResponsiveValue, - Tooltip, } from "@chakra-ui/react" import { fixedPointNumberToString, @@ -13,6 +12,7 @@ import { numberToLocaleString, } from "#/utils" import { CurrencyType, AmountType } from "#/types" +import Tooltip from "../Tooltip" export type CurrencyBalanceProps = { currency: CurrencyType diff --git a/dapp/src/components/shared/InfoTooltip.tsx b/dapp/src/components/shared/InfoTooltip.tsx index 2f7731fa6..a9394b460 100644 --- a/dapp/src/components/shared/InfoTooltip.tsx +++ b/dapp/src/components/shared/InfoTooltip.tsx @@ -1,6 +1,7 @@ import React from "react" import { IconInfoCircleFilled } from "@tabler/icons-react" -import { Icon, Tooltip, TooltipProps } from "@chakra-ui/react" +import { Icon, TooltipProps } from "@chakra-ui/react" +import Tooltip from "./Tooltip" // TODO: Define in the new color palette const ICON_COLOR = "#3A3328" diff --git a/dapp/src/components/shared/Tooltip.tsx b/dapp/src/components/shared/Tooltip.tsx new file mode 100644 index 000000000..924e0e950 --- /dev/null +++ b/dapp/src/components/shared/Tooltip.tsx @@ -0,0 +1,19 @@ +import React, { useState } from "react" +import { Box, Tooltip as ChakraTooltip, TooltipProps } from "@chakra-ui/react" + +export default function Tooltip(props: TooltipProps) { + const { children, ...restProps } = props + const [isOpen, setIsOpen] = useState(false) + + return ( + + setIsOpen(true)} + onMouseLeave={() => setIsOpen(false)} + onClick={() => setIsOpen(true)} + > + {children} + + + ) +} From ca2f1cbf84c034cdf269a4d5804b0fb9281b2bca Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 20 Nov 2024 16:10:04 +0100 Subject: [PATCH 10/51] Use a capital letter for "Acre App" --- dapp/src/components/MobileModeBanner/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dapp/src/components/MobileModeBanner/index.tsx b/dapp/src/components/MobileModeBanner/index.tsx index 672a11ef8..aefba45dd 100644 --- a/dapp/src/components/MobileModeBanner/index.tsx +++ b/dapp/src/components/MobileModeBanner/index.tsx @@ -46,7 +46,7 @@ function MobileModeBanner(props: MobileModeBannerProps) { > - Acre app is on + Acre App is on desktop! @@ -92,7 +92,7 @@ function MobileModeBanner(props: MobileModeBannerProps) {

- Acre app live only on desktop for now. We're working with + Acre App live only on desktop for now. We're working with partners to bring it to mobile soon.

From 4bef001d8db09d72cf5c8a7a2e98866209e74e72 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 20 Nov 2024 16:39:37 +0100 Subject: [PATCH 11/51] Add missing `gridTemplateColumns` --- dapp/src/pages/DashboardPage/index.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dapp/src/pages/DashboardPage/index.tsx b/dapp/src/pages/DashboardPage/index.tsx index f2be13b21..e0fb11bc2 100644 --- a/dapp/src/pages/DashboardPage/index.tsx +++ b/dapp/src/pages/DashboardPage/index.tsx @@ -28,6 +28,12 @@ export default function DashboardPage() { "dashboard beehive" `, }} + gridTemplateColumns={{ + base: "1fr", + sm: "1fr 1fr", + lg: "1fr 31%", + "2xl": "1fr 36%", + }} gridTemplateRows={{ base: ` ${featureFlags.TVL_ENABLED ? "auto" : ""} From aa32912f2ad27c2c947276817f2fe498a03c36e4 Mon Sep 17 00:00:00 2001 From: Rafal Czajkowski Date: Wed, 20 Nov 2024 17:23:58 +0100 Subject: [PATCH 12/51] Set custom config for Gelato sender Extend the timeout for checking the transaction result for Gelato. --- sdk/src/acre.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sdk/src/acre.ts b/sdk/src/acre.ts index d1a84eabd..652dc5a25 100644 --- a/sdk/src/acre.ts +++ b/sdk/src/acre.ts @@ -85,7 +85,9 @@ class Acre { const orangeKit = await OrangeKitSdk.init( Number(ethereumChainId), ethereumRpcUrl, - new GelatoTransactionSender(gelatoApiKey), + new GelatoTransactionSender(gelatoApiKey, { + backoffRetrier: { retries: 7, backoffStepMs: 3000 }, + }), ) const contracts = await getEthereumContracts( From 7b2b48c0e33bfc404e7ff1b27c784ef41475d8d6 Mon Sep 17 00:00:00 2001 From: Rafal Czajkowski Date: Wed, 20 Nov 2024 21:31:55 +0100 Subject: [PATCH 13/51] Update the referral mechanism Detect the referral code in the main router loader instead of the hooks. Using a router loader is simpler and we avoid race between two hooks `useDetectEmbed` and `useDetectReferral`. We noticed a bug with hooks implementation - `acre.referral` set to `0` for Ledger Live after clearing local storage. The `acre.referral` key should always be set to `2083` value for users using Acre in Ledger Live. --- dapp/src/hooks/index.ts | 1 - dapp/src/hooks/useDetectReferral.ts | 10 ------ dapp/src/hooks/useInitApp.ts | 2 -- dapp/src/hooks/useLocalStorage.ts | 7 ++++- dapp/src/hooks/useReferral.ts | 48 ++++++----------------------- dapp/src/router/index.tsx | 19 ++++++++++++ 6 files changed, 34 insertions(+), 53 deletions(-) delete mode 100644 dapp/src/hooks/useDetectReferral.ts diff --git a/dapp/src/hooks/index.ts b/dapp/src/hooks/index.ts index 9584fa5eb..28bc42703 100644 --- a/dapp/src/hooks/index.ts +++ b/dapp/src/hooks/index.ts @@ -27,7 +27,6 @@ export { default as useMobileMode } from "./useMobileMode" export { default as useBitcoinRecoveryAddress } from "./useBitcoinRecoveryAddress" export { default as useIsFetchedWalletData } from "./useIsFetchedWalletData" export { default as useLocalStorage } from "./useLocalStorage" -export { default as useDetectReferral } from "./useDetectReferral" export { default as useReferral } from "./useReferral" export { default as useMats } from "./useMats" export { default as useIsEmbed } from "./useIsEmbed" diff --git a/dapp/src/hooks/useDetectReferral.ts b/dapp/src/hooks/useDetectReferral.ts deleted file mode 100644 index e32a457b6..000000000 --- a/dapp/src/hooks/useDetectReferral.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { useEffect } from "react" -import useReferral from "./useReferral" - -export default function useDetectReferral() { - const { detectReferral } = useReferral() - - useEffect(() => { - detectReferral() - }, [detectReferral]) -} diff --git a/dapp/src/hooks/useInitApp.ts b/dapp/src/hooks/useInitApp.ts index e87e8955a..caf792595 100644 --- a/dapp/src/hooks/useInitApp.ts +++ b/dapp/src/hooks/useInitApp.ts @@ -4,7 +4,6 @@ import { useAccountsChangedOKX } from "./orangeKit/useAccountsChangedOKX" import { useInitDataFromSdk, useInitializeAcreSdk } from "./sdk" import { useSentry } from "./sentry" import useDetectEmbed from "./useDetectEmbed" -import useDetectReferral from "./useDetectReferral" import { useDisconnectWallet } from "./useDisconnectWallet" import { useFetchBTCPriceUSD } from "./useFetchBTCPriceUSD" @@ -13,7 +12,6 @@ export function useInitApp() { // useDetectThemeMode() useSentry() useDetectEmbed() - useDetectReferral() useInitializeAcreSdk() useInitDataFromSdk() useFetchBTCPriceUSD() diff --git a/dapp/src/hooks/useLocalStorage.ts b/dapp/src/hooks/useLocalStorage.ts index d3d03e990..73272cecd 100644 --- a/dapp/src/hooks/useLocalStorage.ts +++ b/dapp/src/hooks/useLocalStorage.ts @@ -1,4 +1,7 @@ -import { useLocalStorage as useRehooksLocalStorage } from "@rehooks/local-storage" +import { + useLocalStorage as useRehooksLocalStorage, + writeStorage, +} from "@rehooks/local-storage" export const parseLocalStorageValue = (value: string | null | undefined) => { if ( @@ -12,6 +15,8 @@ export const parseLocalStorageValue = (value: string | null | undefined) => { return value } +export { writeStorage } + export const getLocalStorageItem = (key: string): string | undefined => { const value = localStorage.getItem(key) return parseLocalStorageValue(value) diff --git a/dapp/src/hooks/useReferral.ts b/dapp/src/hooks/useReferral.ts index d919850e9..4e6f7566c 100644 --- a/dapp/src/hooks/useReferral.ts +++ b/dapp/src/hooks/useReferral.ts @@ -1,52 +1,23 @@ import { env } from "#/constants" -import { referralProgram } from "#/utils" - import { useCallback, useMemo } from "react" -import { MODAL_TYPES } from "#/types" -import useIsEmbed from "./useIsEmbed" -import useLocalStorage from "./useLocalStorage" -import { useModal } from "./useModal" +import useLocalStorage, { writeStorage } from "./useLocalStorage" type UseReferralReturn = { referral: number | null - detectReferral: () => void resetReferral: () => void } +const LOCAL_STORAGE_KEY = "acre.referral" + +export const writeReferral = (value: string) => { + writeStorage(LOCAL_STORAGE_KEY, value) +} + export default function useReferral(): UseReferralReturn { const [referral, setReferral] = useLocalStorage( - "acre.referral", + LOCAL_STORAGE_KEY, env.REFERRAL, ) - const { openModal } = useModal() - const { isEmbed, embeddedApp } = useIsEmbed() - - const detectReferral = useCallback(() => { - const param = referralProgram.getReferralFromURL() - - if (isEmbed && embeddedApp) { - setReferral(referralProgram.getReferralByEmbeddedApp(embeddedApp)) - return - } - - if (param === null) { - setReferral(env.REFERRAL) - return - } - - const convertedReferral = Number(param) - - if (referralProgram.isValidReferral(convertedReferral)) { - setReferral(convertedReferral) - } else { - console.error("Incorrect referral") - setReferral(null) - openModal(MODAL_TYPES.UNEXPECTED_ERROR, { - withCloseButton: false, - closeOnEsc: false, - }) - } - }, [isEmbed, embeddedApp, openModal, setReferral]) const resetReferral = useCallback(() => { setReferral(env.REFERRAL) @@ -54,10 +25,9 @@ export default function useReferral(): UseReferralReturn { return useMemo( () => ({ - detectReferral, resetReferral, referral, }), - [detectReferral, resetReferral, referral], + [resetReferral, referral], ) } diff --git a/dapp/src/router/index.tsx b/dapp/src/router/index.tsx index 9d6a42b0f..de54de5bc 100644 --- a/dapp/src/router/index.tsx +++ b/dapp/src/router/index.tsx @@ -12,6 +12,7 @@ import AccessPage from "#/pages/AccessPage" import WelcomePage from "#/pages/WelcomePage" import welcomePageLoader from "#/pages/WelcomePage/loader" import accessPageLoader from "#/pages/AccessPage/loader" +import { writeReferral } from "#/hooks/useReferral" import { routerPath } from "./path" const mainLayoutLoader: LoaderFunction = ({ request }) => { @@ -32,6 +33,24 @@ export const router = createBrowserRouter([ { path: "/", element: , + loader: ({ request }) => { + // TODO: display the error page/modal when the referral is invalid. + const referralCode = referralProgram.getReferralFromURL() + if ( + referralCode && + referralProgram.isValidReferral(Number(referralCode)) + ) { + writeReferral(referralCode) + } + + const embedApp = referralProgram.getEmbeddedApp(request.url) + if (referralProgram.isEmbedApp(embedApp)) { + writeReferral( + referralProgram.getReferralByEmbeddedApp(embedApp).toString(), + ) + } + return null + }, children: [ { index: true, From 15bac3d35ab3932a886ce3430b8a9d060d83a573 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Thu, 21 Nov 2024 08:23:04 +0100 Subject: [PATCH 14/51] Add more info for deposit/withdraw tooltips --- dapp/src/pages/DashboardPage/PositionDetails.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/dapp/src/pages/DashboardPage/PositionDetails.tsx b/dapp/src/pages/DashboardPage/PositionDetails.tsx index 77b55cd5e..0cb375b24 100644 --- a/dapp/src/pages/DashboardPage/PositionDetails.tsx +++ b/dapp/src/pages/DashboardPage/PositionDetails.tsx @@ -43,9 +43,6 @@ export default function PositionDetails() { const openWithdrawModal = useTransactionModal(ACTION_FLOW_TYPES.UNSTAKE) const activitiesCount = useAllActivitiesCount() const isMobileMode = useMobileMode() - const arrivingSoonLabel = isMobileMode - ? "Arriving Soon to mobile devices" - : undefined const { tvl } = useStatistics() @@ -97,7 +94,7 @@ export default function PositionDetails() { diff --git a/dapp/src/vite-env.d.ts b/dapp/src/vite-env.d.ts index 53f7175b8..564bf6a80 100644 --- a/dapp/src/vite-env.d.ts +++ b/dapp/src/vite-env.d.ts @@ -17,6 +17,7 @@ interface ImportMetaEnv { readonly VITE_SUBGRAPH_API_KEY: string readonly VITE_LATEST_COMMIT_HASH: string readonly VITE_ACRE_API_ENDPOINT: string + readonly VITE_FEATURE_MOBILE_MODE_ENABLED: string } interface ImportMeta { From aafe02f5533dee549adc45c78332480caefb5931 Mon Sep 17 00:00:00 2001 From: Rafal Czajkowski Date: Fri, 22 Nov 2024 15:37:05 +0100 Subject: [PATCH 31/51] Update main router loader Handle a case when someone passes invalid referral code via URL. We should set the default value in local storage instaed of using the previous one. --- dapp/src/router/index.tsx | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/dapp/src/router/index.tsx b/dapp/src/router/index.tsx index f1a65ef10..1a5b3ced0 100644 --- a/dapp/src/router/index.tsx +++ b/dapp/src/router/index.tsx @@ -36,13 +36,15 @@ export const router = createBrowserRouter([ element: , loader: ({ request }) => { // TODO: display the error page/modal when the referral is invalid. - const referralCode = referralProgram.getReferralFromURL() ?? env.REFERRAL - if ( - referralCode && - referralProgram.isValidReferral(Number(referralCode)) - ) { - writeReferral(referralCode.toString()) - } + const referralCodeFromUrl = referralProgram.getReferralFromURL() + + const referralCode = referralProgram.isValidReferral( + Number(referralCodeFromUrl), + ) + ? referralCodeFromUrl! + : env.REFERRAL + + writeReferral(referralCode.toString()) const embedApp = referralProgram.getEmbeddedApp(request.url) if (referralProgram.isEmbedApp(embedApp)) { From 8ea9ba42db3d0cdb07df14ee983da1af07dab16c Mon Sep 17 00:00:00 2001 From: Rafal Czajkowski Date: Fri, 22 Nov 2024 17:34:44 +0100 Subject: [PATCH 32/51] Bump `orangekit` packages to the latest versions --- dapp/package.json | 2 +- pnpm-lock.yaml | 39 ++++++++++++++++++++++++++++----------- sdk/package.json | 2 +- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/dapp/package.json b/dapp/package.json index 97601a1a3..b384d7b43 100644 --- a/dapp/package.json +++ b/dapp/package.json @@ -23,7 +23,7 @@ "@emotion/styled": "^11.11.0", "@ledgerhq/wallet-api-acre-module": "0.1.0", "@ledgerhq/wallet-api-client": "1.6.0", - "@orangekit/react": "1.0.0-beta.33", + "@orangekit/react": "1.0.0-beta.34", "@orangekit/sign-in-with-wallet": "1.0.0-beta.6", "@reduxjs/toolkit": "^2.2.0", "@rehooks/local-storage": "^2.4.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cf2c53ac6..53c684f24 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -39,8 +39,8 @@ importers: specifier: 1.6.0 version: 1.6.0 '@orangekit/react': - specifier: 1.0.0-beta.33 - version: 1.0.0-beta.33(@react-native-async-storage/async-storage@1.23.1(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10)))(@tanstack/query-core@5.45.0)(@tanstack/react-query@5.45.0(react@18.3.1))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(rollup@4.18.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8) + specifier: 1.0.0-beta.34 + version: 1.0.0-beta.34(@react-native-async-storage/async-storage@1.23.1(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10)))(@tanstack/query-core@5.45.0)(@tanstack/react-query@5.45.0(react@18.3.1))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(rollup@4.18.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8) '@orangekit/sign-in-with-wallet': specifier: 1.0.0-beta.6 version: 1.0.0-beta.6(bech32@2.0.0)(ethers@6.13.0(bufferutil@4.0.8)(utf-8-validate@5.0.10)) @@ -172,8 +172,8 @@ importers: specifier: 2.5.0-dev.3 version: 2.5.0-dev.3(@keep-network/keep-core@1.8.1-dev.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10) '@orangekit/sdk': - specifier: 1.0.0-beta.18 - version: 1.0.0-beta.18(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10) + specifier: 1.0.0-beta.19 + version: 1.0.0-beta.19(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10) ethers: specifier: 6.10.0 version: 6.10.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) @@ -2692,11 +2692,11 @@ packages: '@orangekit/contracts@1.0.0-beta.3': resolution: {integrity: sha512-xP1Oz/JzuHypg5DcsHayINhFSL5M/tCmRP/stmNAvjeebXhrKuALKAHWn98H0Mo3QfYYrz8UcltQPeH6+68n6A==} - '@orangekit/react@1.0.0-beta.33': - resolution: {integrity: sha512-b5VMFB2tZad86FNdtylwsKaXlXlrSjY9cIMsaJMUh7EEWEoVvtndbCsHrISKbspm7y+S5nNmGlE3WcQvR8RWWw==} + '@orangekit/react@1.0.0-beta.34': + resolution: {integrity: sha512-/PTfYcu/BU4ssltIuy+AKqbaGzue+MEJHwd7+4aZhXhwJ+/xrYo3mJ1tSwj6K8lAJCl/N25vq7zNJgVgjLK1WQ==} - '@orangekit/sdk@1.0.0-beta.18': - resolution: {integrity: sha512-031JkI0F8gdGzj/7sKbJ52k0Xj/E4uwp/O0SWFDCXyZC0vwtjlw3ItAaZz+nIj820b6dSM6pjL+P7um3m9AK3Q==} + '@orangekit/sdk@1.0.0-beta.19': + resolution: {integrity: sha512-sIqzu3QTb0WkB4Ir4zHX4tP7hf+uZBXX60q/ww6UzwPjoqGL3dOdui59lTZSNygdMbydLE3y9FSNZPNkQvm+gA==} '@orangekit/sign-in-with-wallet-parser@1.0.0-beta.6': resolution: {integrity: sha512-Yi6ohSJV4/Ovrq5c7jD+kPE8pZxLhWtFbZjKRwUW8JL60P/tcyT5o0etul0reqcY2iBlIo5aoC2Hh0noRGl86w==} @@ -3113,6 +3113,10 @@ packages: peerDependencies: ethers: 5.4.0 + '@safe-global/safe-core-sdk-types@4.1.1': + resolution: {integrity: sha512-5NIWG7OjV+C5iquux0yPcu8SHUzg1qJXJ/jAQcPwXGTC7ZVsFawnR43/l2Vg9zEwf0RF0xTm3W8DXkaBYORiEQ==} + deprecated: 'WARNING: This project has been renamed to @safe-global/types-kit. Please, migrate from @safe-global/safe-core-sdk-types@5.1.0 to @safe-global/types-kit@1.0.0.' + '@safe-global/safe-core-sdk-types@5.0.1': resolution: {integrity: sha512-xIlHZ9kaAIwEhR0OY0i2scdcQyrc0tDJ+eZZ04lhvg81cgYLY1Z5wfJQqazR2plPT1Hz0A9C79jYdUVvzoF/tw==} @@ -14831,9 +14835,9 @@ snapshots: transitivePeerDependencies: - ethers - '@orangekit/react@1.0.0-beta.33(@react-native-async-storage/async-storage@1.23.1(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10)))(@tanstack/query-core@5.45.0)(@tanstack/react-query@5.45.0(react@18.3.1))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(rollup@4.18.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)': + '@orangekit/react@1.0.0-beta.34(@react-native-async-storage/async-storage@1.23.1(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10)))(@tanstack/query-core@5.45.0)(@tanstack/react-query@5.45.0(react@18.3.1))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(rollup@4.18.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)': dependencies: - '@orangekit/sdk': 1.0.0-beta.18(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10) + '@orangekit/sdk': 1.0.0-beta.19(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10) '@rainbow-me/rainbowkit': 2.0.2(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(viem@2.8.16(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(wagmi@2.5.12(@react-native-async-storage/async-storage@1.23.1(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10)))(@tanstack/query-core@5.45.0)(@tanstack/react-query@5.45.0(react@18.3.1))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react-native@0.74.2(@babel/core@7.24.7)(@babel/preset-env@7.24.7(@babel/core@7.24.7))(@types/react@18.3.3)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.18.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.8.16(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)) ethers: 6.12.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) react: 18.3.1 @@ -14870,13 +14874,14 @@ snapshots: - utf-8-validate - zod - '@orangekit/sdk@1.0.0-beta.18(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10)': + '@orangekit/sdk@1.0.0-beta.19(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10)': dependencies: '@gelatonetwork/relay-sdk': 5.5.6(bufferutil@4.0.8)(utf-8-validate@5.0.10) '@noble/curves': 1.4.0 '@noble/hashes': 1.4.0 '@orangekit/contracts': 1.0.0-beta.3(ethers@6.12.1(bufferutil@4.0.8)(utf-8-validate@5.0.10)) '@safe-global/protocol-kit': 3.1.1(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10) + '@safe-global/safe-core-sdk-types': 4.1.1(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10) bitcoinjs-lib: 6.1.5 ethers: 6.12.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) transitivePeerDependencies: @@ -15492,6 +15497,18 @@ snapshots: dependencies: ethers: 6.12.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@safe-global/safe-core-sdk-types@4.1.1(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10)': + dependencies: + '@safe-global/safe-deployments': 1.37.0 + ethers: 6.10.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) + web3-core: 1.10.4(encoding@0.1.13) + web3-utils: 1.10.4 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - utf-8-validate + '@safe-global/safe-core-sdk-types@5.0.1(typescript@5.4.5)(zod@3.23.8)': dependencies: abitype: 1.0.2(typescript@5.4.5)(zod@3.23.8) diff --git a/sdk/package.json b/sdk/package.json index 2a79b6f5d..9a67628dc 100644 --- a/sdk/package.json +++ b/sdk/package.json @@ -27,7 +27,7 @@ "dependencies": { "@acre-btc/contracts": "workspace:*", "@keep-network/tbtc-v2.ts": "2.5.0-dev.3", - "@orangekit/sdk": "1.0.0-beta.18", + "@orangekit/sdk": "1.0.0-beta.19", "ethers": "6.10.0", "ethers-v5": "npm:ethers@^5.5.2" } From e5cf76279c42aed6f7a646445307e80b48e49627 Mon Sep 17 00:00:00 2001 From: Rafal Czajkowski Date: Fri, 22 Nov 2024 18:52:08 +0100 Subject: [PATCH 33/51] Update `ConnectWallet` component Implement a mobile version of this component - display dropdown with options: - copy address, - swtich account (if this feature is supported by embedded app), - disconnect. --- dapp/src/components/Header/ConnectWallet.tsx | 51 +++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/dapp/src/components/Header/ConnectWallet.tsx b/dapp/src/components/Header/ConnectWallet.tsx index b1b598746..32072522b 100644 --- a/dapp/src/components/Header/ConnectWallet.tsx +++ b/dapp/src/components/Header/ConnectWallet.tsx @@ -5,11 +5,15 @@ import { HStack, Icon, IconButton, + Menu, + MenuButton, + MenuItem, + MenuList, StackDivider, useClipboard, useMultiStyleConfig, } from "@chakra-ui/react" -import { useIsEmbed, useModal, useWallet } from "#/hooks" +import { useIsEmbed, useMobileMode, useModal, useWallet } from "#/hooks" import { CurrencyBalance } from "#/components/shared/CurrencyBalance" import { TextMd } from "#/components/shared/Typography" import { BitcoinIcon } from "#/assets/icons" @@ -21,6 +25,8 @@ import { IconLogout, IconWallet, IconUserCode, + IconChevronDown, + IconChevronUp, } from "@tabler/icons-react" import { useMatch } from "react-router-dom" import Tooltip from "../shared/Tooltip" @@ -39,6 +45,7 @@ export default function ConnectWallet() { size: "lg", }) const isDashboardPage = useMatch("/dashboard") + const isMobile = useMobileMode() const handleConnectWallet = (isReconnecting: boolean = false) => { openModal(MODAL_TYPES.CONNECT_WALLET, { isReconnecting }) @@ -63,7 +70,47 @@ export default function ConnectWallet() { ) } - return ( + return isMobile ? ( + + {({ isOpen }) => ( + <> + } + rightIcon={isOpen ? : } + > + {truncateAddress(address)} + + + } + onClick={onCopy} + > + {hasCopied ? "Address copied" : "Copy Address"} + + {isChangeAccountFeatureSupported(embeddedApp) && ( + } + onClick={() => handleConnectWallet(true)} + > + Change account + + )} + } + onClick={onDisconnect} + > + Disconnect + + + + )} + + ) : ( From f2d48ad920d4b0dc645513aba03a49481c9d0895 Mon Sep 17 00:00:00 2001 From: Rafal Czajkowski Date: Mon, 25 Nov 2024 11:00:32 +0100 Subject: [PATCH 34/51] Improve `isValidReferral` fn Accept only numbers in string w/o leading zeros. --- dapp/src/router/index.tsx | 4 +--- dapp/src/utils/referralProgram.ts | 20 +++++++++++++++++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/dapp/src/router/index.tsx b/dapp/src/router/index.tsx index 1a5b3ced0..351a8504e 100644 --- a/dapp/src/router/index.tsx +++ b/dapp/src/router/index.tsx @@ -38,9 +38,7 @@ export const router = createBrowserRouter([ // TODO: display the error page/modal when the referral is invalid. const referralCodeFromUrl = referralProgram.getReferralFromURL() - const referralCode = referralProgram.isValidReferral( - Number(referralCodeFromUrl), - ) + const referralCode = referralProgram.isValidReferral(referralCodeFromUrl) ? referralCodeFromUrl! : env.REFERRAL diff --git a/dapp/src/utils/referralProgram.ts b/dapp/src/utils/referralProgram.ts index 36f48b9a3..82a3bfbc5 100644 --- a/dapp/src/utils/referralProgram.ts +++ b/dapp/src/utils/referralProgram.ts @@ -9,9 +9,23 @@ const EMBEDDED_APP_TO_REFERRAL: Record = { "ledger-live": 2083, } -const isValidReferral = (value: number) => { - const isInteger = Number.isInteger(value) - return isInteger && value >= 0 && value <= MAX_UINT16 +const isValidReferral = (value: unknown) => { + let valueAsNumber: number | undefined + + if (typeof value === "string") { + // Only digits w/o leading zeros. + const isNumber = /^(?:[1-9][0-9]*|0)$/.test(value) + valueAsNumber = isNumber ? Number(value) : undefined + } else if (typeof value === "number") { + valueAsNumber = value + } + + return ( + !!valueAsNumber && + Number.isInteger(valueAsNumber) && + valueAsNumber >= 0 && + valueAsNumber <= MAX_UINT16 + ) } const getReferralFromURL = () => From 6d2f0135b80f5b829f1d6c5996075aa0d1b67ed9 Mon Sep 17 00:00:00 2001 From: Jakub Date: Mon, 25 Nov 2024 16:08:53 +0100 Subject: [PATCH 35/51] Enable Sentry ExtraErrorData integration Enable [ExtraErrorData](https://docs.sentry.io/platforms/javascript/guides/react/configuration/integrations/extraerrordata/) integration in Sentry. This integration serialized extra data attached to the error event. It is useful to attach additional context to the error event, as currently the objects are not serialized and are visible as `[Object]` in the Sentry dashboard. --- dapp/src/sentry/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/dapp/src/sentry/index.ts b/dapp/src/sentry/index.ts index 0bb08159d..67b04bf96 100644 --- a/dapp/src/sentry/index.ts +++ b/dapp/src/sentry/index.ts @@ -6,6 +6,7 @@ const initialize = (dsn: string) => { integrations: [ Sentry.browserTracingIntegration(), Sentry.captureConsoleIntegration({ levels: ["error"] }), + Sentry.extraErrorDataIntegration(), ], // Attach stacktrace to errors logged by `console.error`. This is useful for // the `captureConsoleIntegration` integration. From 1674a5ae16aed8520059084e057c022faa56fd41 Mon Sep 17 00:00:00 2001 From: Jakub Date: Mon, 25 Nov 2024 16:10:59 +0100 Subject: [PATCH 36/51] Enable Sentry HttpClient integration Enable [HttpClient](https://docs.sentry.io/platforms/javascript/guides/react/configuration/integrations/httpclient/) integration in Sentry. This integration will capture failed requests and responses in Sentry. --- dapp/src/sentry/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/dapp/src/sentry/index.ts b/dapp/src/sentry/index.ts index 67b04bf96..3174c1a44 100644 --- a/dapp/src/sentry/index.ts +++ b/dapp/src/sentry/index.ts @@ -7,6 +7,7 @@ const initialize = (dsn: string) => { Sentry.browserTracingIntegration(), Sentry.captureConsoleIntegration({ levels: ["error"] }), Sentry.extraErrorDataIntegration(), + Sentry.httpClientIntegration(), ], // Attach stacktrace to errors logged by `console.error`. This is useful for // the `captureConsoleIntegration` integration. From d94b6c203230beb4ffbdfb14b418226e325e83d9 Mon Sep 17 00:00:00 2001 From: Rafal Czajkowski Date: Tue, 26 Nov 2024 12:31:04 +0100 Subject: [PATCH 37/51] Update modal styles on mobile --- .../TransactionModal/ActionFormModal.tsx | 2 +- .../TransactionModal/ResumeModal.tsx | 2 +- .../TransactionModal/SuccessModal.tsx | 2 +- .../WalletInteractionModal.tsx | 2 +- dapp/src/theme/Modal.ts | 32 +++++++++++-------- dapp/src/theme/utils/semanticTokens.ts | 15 +++++++-- 6 files changed, 34 insertions(+), 21 deletions(-) diff --git a/dapp/src/components/TransactionModal/ActionFormModal.tsx b/dapp/src/components/TransactionModal/ActionFormModal.tsx index 53ab0e42b..8c50be64e 100644 --- a/dapp/src/components/TransactionModal/ActionFormModal.tsx +++ b/dapp/src/components/TransactionModal/ActionFormModal.tsx @@ -107,7 +107,7 @@ function ActionFormModal({ type }: { type: ActionFlowType }) { <> {!isLoading && } {heading} - + diff --git a/dapp/src/components/TransactionModal/ResumeModal.tsx b/dapp/src/components/TransactionModal/ResumeModal.tsx index 16cb45999..bc2159265 100644 --- a/dapp/src/components/TransactionModal/ResumeModal.tsx +++ b/dapp/src/components/TransactionModal/ResumeModal.tsx @@ -22,7 +22,7 @@ export default function ResumeModal({ closeModal }: BaseModalProps) { return ( <> - + Paused diff --git a/dapp/src/components/TransactionModal/SuccessModal.tsx b/dapp/src/components/TransactionModal/SuccessModal.tsx index e03d49658..5390a7e7f 100644 --- a/dapp/src/components/TransactionModal/SuccessModal.tsx +++ b/dapp/src/components/TransactionModal/SuccessModal.tsx @@ -32,7 +32,7 @@ export default function SuccessModal({ type }: SuccessModalProps) { return ( <> - + {ACTION_FLOW_TYPES.UNSTAKE === type ? "Withdrawal initiated!" : "Deposit received!"} diff --git a/dapp/src/components/TransactionModal/WalletInteractionModal.tsx b/dapp/src/components/TransactionModal/WalletInteractionModal.tsx index dbbf4c53b..84a8469aa 100644 --- a/dapp/src/components/TransactionModal/WalletInteractionModal.tsx +++ b/dapp/src/components/TransactionModal/WalletInteractionModal.tsx @@ -54,7 +54,7 @@ export default function WalletInteractionModal({ return ( <> {step === "opening-wallet" && } - + {header} diff --git a/dapp/src/theme/Modal.ts b/dapp/src/theme/Modal.ts index fd79f1bdc..bd1846073 100644 --- a/dapp/src/theme/Modal.ts +++ b/dapp/src/theme/Modal.ts @@ -2,23 +2,27 @@ import { modalAnatomy as parts } from "@chakra-ui/anatomy" import { createMultiStyleConfigHelpers, defineStyle } from "@chakra-ui/react" const baseStyleContainer = defineStyle({ - px: 8, + px: { base: 3, md: 8 }, }) const baseStyleDialog = defineStyle({ - marginTop: { base: 12, sm: "var(--chakra-space-modal_shift)" }, + marginTop: { + base: "var(--chakra-space-modal_shift)", + md: "var(--chakra-space-modal_shift_xl)", + }, marginBottom: 8, boxShadow: "none", borderRadius: "xl", + p: { base: 5 }, bg: "gold.100", border: "none", }) const baseCloseButton = defineStyle({ - top: -7, - right: -7, - boxSize: 7, - rounded: "100%", + top: { base: 3, md: -7 }, + right: { base: 3, md: -7 }, + boxSize: { md: 7 }, + rounded: { md: "100%" }, bg: "opacity.white.5", _hover: { @@ -37,9 +41,9 @@ const baseStyleHeader = defineStyle({ fontSize: "xl", lineHeight: "xl", fontWeight: "bold", - pt: 10, - px: 10, - pb: 8, + pt: { md: 10 }, + px: { md: 10 }, + mb: 8, }) const baseStyleBody = defineStyle({ @@ -50,15 +54,15 @@ const baseStyleBody = defineStyle({ alignItems: "center", gap: 6, pt: 0, - px: 8, - pb: 10, + px: { base: 0, md: 8 }, + pb: { base: 0, md: 10 }, }) const baseStyleFooter = defineStyle({ flexDirection: "column", gap: 6, - px: 8, - pb: 10, + px: { base: 0, md: 8 }, + pb: { base: 0, md: 10 }, }) const multiStyleConfig = createMultiStyleConfigHelpers(parts.keys) @@ -87,7 +91,7 @@ const sizeXl = multiStyleConfig.definePartsStyle({ }) const sizeLg = multiStyleConfig.definePartsStyle({ - dialog: { w: "30rem" }, + dialog: { w: { xs: "95%" } }, }) const sizeFull = multiStyleConfig.definePartsStyle({ diff --git a/dapp/src/theme/utils/semanticTokens.ts b/dapp/src/theme/utils/semanticTokens.ts index 8ad1298ba..dfd56d42b 100644 --- a/dapp/src/theme/utils/semanticTokens.ts +++ b/dapp/src/theme/utils/semanticTokens.ts @@ -1,8 +1,17 @@ +const headerHeight = 28 +const headerHeightXl = 36 + +const modalShiftToHeaderHeight = { + [headerHeight]: 28, + [headerHeightXl]: "9.25rem", +} + export const semanticTokens = { space: { - header_height: 28, - header_height_xl: 36, - modal_shift: "9.75rem", // 156px + header_height: headerHeight, + header_height_xl: headerHeightXl, + modal_shift: modalShiftToHeaderHeight[headerHeight], + modal_shift_xl: modalShiftToHeaderHeight[headerHeightXl], dashboard_card_padding: 5, }, sizes: { From 108533649e916859402762545b8a1278d8cb6d06 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Tue, 26 Nov 2024 15:57:50 +0100 Subject: [PATCH 38/51] Copy change for dApp --- .../BuildTransactionModal.tsx | 4 ++-- .../TransactionModal/WalletInteractionModal.tsx | 17 ++++++++++++----- .../src/pages/DashboardPage/PositionDetails.tsx | 2 +- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/dapp/src/components/TransactionModal/ActiveUnstakingStep/BuildTransactionModal.tsx b/dapp/src/components/TransactionModal/ActiveUnstakingStep/BuildTransactionModal.tsx index c6b6f81af..84c3069b3 100644 --- a/dapp/src/components/TransactionModal/ActiveUnstakingStep/BuildTransactionModal.tsx +++ b/dapp/src/components/TransactionModal/ActiveUnstakingStep/BuildTransactionModal.tsx @@ -16,10 +16,10 @@ export default function BuildTransactionModal({ return ( <> - Building transaction data... + Preparing withdrawal transaction... - We are building your withdrawal data. + This may take a few minutes. diff --git a/dapp/src/components/TransactionModal/WalletInteractionModal.tsx b/dapp/src/components/TransactionModal/WalletInteractionModal.tsx index dbbf4c53b..8a3da5e94 100644 --- a/dapp/src/components/TransactionModal/WalletInteractionModal.tsx +++ b/dapp/src/components/TransactionModal/WalletInteractionModal.tsx @@ -10,8 +10,8 @@ import { ProgressProps, } from "@chakra-ui/react" import { AcreSignIcon } from "#/assets/icons" -import { useActionFlowType, useConnector } from "#/hooks" -import { ACTION_FLOW_TYPES } from "#/types" +import { useActionFlowType, useConnector, useIsEmbed } from "#/hooks" +import { ACTION_FLOW_TYPES, DappMode } from "#/types" import { Alert, AlertIcon } from "../shared/Alert" import { TextMd } from "../shared/Typography" @@ -22,11 +22,16 @@ const ICON_STYLES = { type WalletInteractionStep = "opening-wallet" | "awaiting-transaction" +const CONTENT_BY_DAPP_MODE: Record = { + standalone: "wallet", + "ledger-live": "Ledger Device", +} + const DATA: Record< WalletInteractionStep, { header: string - description: (action: string) => string + description: (action: string, mode: DappMode) => string progressProps?: ProgressProps } > = { @@ -37,7 +42,8 @@ const DATA: Record< }, "awaiting-transaction": { header: "Awaiting signature confirmation", - description: () => "Waiting for your wallet to confirm the transaction.", + description: (_, mode: DappMode) => + `Communicating with your ${CONTENT_BY_DAPP_MODE[mode]}...`, progressProps: { transform: "scaleX(-1)" }, }, } @@ -50,6 +56,7 @@ export default function WalletInteractionModal({ const actionType = useActionFlowType() const connector = useConnector() const { header, description, progressProps } = DATA[step] + const { embeddedApp } = useIsEmbed() return ( <> @@ -78,6 +85,7 @@ export default function WalletInteractionModal({ {description( actionType === ACTION_FLOW_TYPES.STAKE ? "deposit" : "withdraw", + embeddedApp ?? "standalone", )} {step === "awaiting-transaction" && ( @@ -85,7 +93,6 @@ export default function WalletInteractionModal({ This may take up to a minute. - Don't close this window. )} diff --git a/dapp/src/pages/DashboardPage/PositionDetails.tsx b/dapp/src/pages/DashboardPage/PositionDetails.tsx index 8346fcc8a..f5b2e30b4 100644 --- a/dapp/src/pages/DashboardPage/PositionDetails.tsx +++ b/dapp/src/pages/DashboardPage/PositionDetails.tsx @@ -56,7 +56,7 @@ export default function PositionDetails() { {/* TODO: Component should be moved to `CardHeader` */} - Your deposit + Your balance {/* TODO: Uncomment when position will be implemented */} {/* {positionPercentage && ( Date: Tue, 26 Nov 2024 21:58:29 +0100 Subject: [PATCH 39/51] Update estimated time for processing of small deposits from 1 hour to 2 hours Deposit duration for small deposits was increased from 1 hour to 2 hours. This change was made to reflect the actual time it takes for small deposits to be processed. We observed that small deposits are taking in general 1.5 hours to finalize, so we decided to round up for better user experience. --- dapp/src/utils/activities.ts | 29 +++++++++++--- dapp/src/utils/tests/activities.test.ts | 52 +++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 5 deletions(-) create mode 100644 dapp/src/utils/tests/activities.test.ts diff --git a/dapp/src/utils/activities.ts b/dapp/src/utils/activities.ts index 7349a985b..a6d1716da 100644 --- a/dapp/src/utils/activities.ts +++ b/dapp/src/utils/activities.ts @@ -21,12 +21,31 @@ export function getEstimatedDuration( amount: bigint, type: ActivityType, ): string { + // Withdrawal duration is related to the tBTC redemption process, which takes + // approximately 5 - 7 hours. We use the average value of 6 hours. if (isWithdrawType(type)) return "6 hours" - if (amount < MIN_LIMIT_VALUE_DURATION) return "1 hour" - - if (amount >= MIN_LIMIT_VALUE_DURATION && amount < MAX_LIMIT_VALUE_DURATION) - return "2 hours" - + // Deposit duration is related to the tBTC minting process, which varies based + // on the amount of BTC deposited. + // Each threshold requires a different number of Bitcoin transaction confirmations: + // <0.1 BTC: 1 Bitcoin block confirmation (~10 minutes), + // >=0.1 BTC and <1 BTC: 3 Bitcoin block confirmations (~30 minutes), + // >=1 BTC: 6 Bitcoin block confirmations (~60 minutes). + // The duration of the transaction minting process depends on the Bitcoin network + // congestion, and the fee paid by the user. + // + // After the required number of Bitcoin block confirmations, the tBTC optimistic + // minting process starts. The optimistic minting process takes approximately + // 1 hour to complete. + // After optimistic minting is completed, the Acre bots will finalize the deposit + // in no more than 10 minutes. + // + // We round the estimated duration up to the nearest hour. + // + // For <0.1 BTC estimated duration is around 1 hour 20 minutes. + if (amount < MIN_LIMIT_VALUE_DURATION) return "2 hours" + // For <1 BTC estimated duration is around 1 hours 40 minutes. + if (amount < MAX_LIMIT_VALUE_DURATION) return "2 hours" + // For >=1 BTC estimated duration is around 2 hours 10 minutes. return "3 hours" } diff --git a/dapp/src/utils/tests/activities.test.ts b/dapp/src/utils/tests/activities.test.ts new file mode 100644 index 000000000..fcafa84a7 --- /dev/null +++ b/dapp/src/utils/tests/activities.test.ts @@ -0,0 +1,52 @@ +import { describe, expect, it } from "vitest" +import { getEstimatedDuration } from "../activities" + +describe("Utils functions for activities", () => { + describe("getEstimatedDuration", () => { + describe("withdraw", () => { + describe.each([ + // 0.01 BTC + { value: 0.01, expectedResult: "6 hours" }, + // 0.1 BTC + { value: 0.1, expectedResult: "6 hours" }, + // 1 BTC + { value: 1, expectedResult: "6 hours" }, + // 10 BTC + { value: 10, expectedResult: "6 hours" }, + ])("when it is $value BTC", ({ value, expectedResult }) => { + it(`should return ${expectedResult}`, () => { + expect(getEstimatedDuration(BigInt(value * 1e8), "withdraw")).toEqual( + expectedResult, + ) + }) + }) + }) + + describe("deposit", () => { + describe.each([ + // 0.0001 BTC + { value: 0.0001, expectedResult: "2 hours" }, + // 0.001 BTC + { value: 0.001, expectedResult: "2 hours" }, + // 0.01 BTC + { value: 0.01, expectedResult: "2 hours" }, + // 0.09 BTC + { value: 0.09, expectedResult: "2 hours" }, + // 0.1 BTC + { value: 0.1, expectedResult: "2 hours" }, + // 0.9 BTC + { value: 0.9, expectedResult: "2 hours" }, + // 1 BTC + { value: 1, expectedResult: "3 hours" }, + // 10 BTC + { value: 10, expectedResult: "3 hours" }, + ])("when it is $value BTC", ({ value, expectedResult }) => { + it(`should return ${expectedResult}`, () => { + expect(getEstimatedDuration(BigInt(value * 1e8), "deposit")).toEqual( + expectedResult, + ) + }) + }) + }) + }) +}) From 2d6c80c94a31d324f5c629f6f9ae62bf4999595b Mon Sep 17 00:00:00 2001 From: Rafal Czajkowski Date: Wed, 27 Nov 2024 13:07:44 +0100 Subject: [PATCH 40/51] Support direct navigation in Ledger Live App To ensure users are directed to the correct LiveApp page for specific actions (such as staking/unstaking) triggered from Ledger Live, the Acre dapp must implement URL parameters to support direct navigation. We want to connect to the account passed via URL. The Ledger Live App passes the `accountId` parameter in URL when redirecting to Acre dapp. This parameter has the following pattern `js:2:bitcoin_testnet::`. To connect to a given account we need to get the extended public key from this parameter. To connect to a given account by xpub we define the new option in the provider: `tryConnectToAccountByXpub`. The Ledger Live Bitcoin provider will try to find this account and connect. --- dapp/src/utils/orangekit/index.ts | 28 +++++++++++++++++++ .../orangekit/ledger-live/bitcoin-provider.ts | 27 ++++++++++++++---- .../tests/bitcoin-provider.test.ts | 2 ++ dapp/src/wagmiConfig.ts | 14 ++++++++-- 4 files changed, 63 insertions(+), 8 deletions(-) diff --git a/dapp/src/utils/orangekit/index.ts b/dapp/src/utils/orangekit/index.ts index 18f355df4..af5317b7c 100644 --- a/dapp/src/utils/orangekit/index.ts +++ b/dapp/src/utils/orangekit/index.ts @@ -107,6 +107,33 @@ async function verifySignInWithWalletMessage( return result.data } +/** + * Finds the extended public key (xpub) of the user's account from URL. Users + * can be redirected to the exact app in the Ledger Live application. One of the + * parameters passed via URL is `accountId` - the ID of the user's account in + * Ledger Live. + * @see https://developers.ledger.com/docs/ledger-live/exchange/earn/liveapp#url-parameters-for-direct-navigation + * + * @param {string} url Request url + * @returns The extended public key (xpub) of the user's account if the search + * parameter `accountId` exists in the URL. Otherwise `undefined`. + */ +function findXpubFromUrl(url: string): string | undefined { + const parsedUrl = new URL(url) + + const accountId = parsedUrl.searchParams.get("accountId") + + if (!accountId) return undefined + + // The fourth value separated by `:` is extended public key. See the + // account ID template: `js:2:bitcoin_testnet::`. + const xpubFromAccountId = accountId.split(":")[3] + + if (!xpubFromAccountId) return undefined + + return xpubFromAccountId +} + export default { getWalletInfo, isWalletInstalled, @@ -119,4 +146,5 @@ export default { isWalletConnectionRejectedError, verifySignInWithWalletMessage, getOrangeKitLedgerLiveConnector, + findXpubFromUrl, } diff --git a/dapp/src/utils/orangekit/ledger-live/bitcoin-provider.ts b/dapp/src/utils/orangekit/ledger-live/bitcoin-provider.ts index 7dab9c5ad..316e628a4 100644 --- a/dapp/src/utils/orangekit/ledger-live/bitcoin-provider.ts +++ b/dapp/src/utils/orangekit/ledger-live/bitcoin-provider.ts @@ -58,9 +58,12 @@ function numberToValidHexString(value: number): string { return `0x${hex}` } -export type AcreLedgerLiveBitcoinProviderOptions = { - tryConnectToAddress: string | undefined -} +export type AcreLedgerLiveBitcoinProviderOptions = + | { + tryConnectToAddress?: string + tryConnectToAccountByXpub?: never + } + | { tryConnectToAddress?: never; tryConnectToAccountByXpub?: string } /** * Ledger Live Wallet API Bitcoin Provider. @@ -90,6 +93,7 @@ export default class AcreLedgerLiveBitcoinProvider network: BitcoinNetwork, options: AcreLedgerLiveBitcoinProviderOptions = { tryConnectToAddress: undefined, + tryConnectToAccountByXpub: undefined, }, ) { const windowMessageTransport = new WindowMessageTransport() @@ -115,6 +119,7 @@ export default class AcreLedgerLiveBitcoinProvider walletApiClient: WalletAPIClient, options: AcreLedgerLiveBitcoinProviderOptions = { tryConnectToAddress: undefined, + tryConnectToAccountByXpub: undefined, }, ) { this.#network = network @@ -140,12 +145,24 @@ export default class AcreLedgerLiveBitcoinProvider currencyIds, }) - if (this.#options.tryConnectToAddress) { + if ( + this.#options.tryConnectToAddress || + this.#options.tryConnectToAccountByXpub + ) { for (let i = 0; i < accounts.length; i += 1) { const acc = accounts[i] + if ( + this.#options.tryConnectToAccountByXpub && + // eslint-disable-next-line no-await-in-loop + (await this.#walletApiClient.bitcoin.getXPub(acc.id)) === + this.#options.tryConnectToAccountByXpub + ) { + this.#account = acc + break + } + // eslint-disable-next-line no-await-in-loop const address = await this.#getAddress(acc.id) - if (address === this.#options.tryConnectToAddress) { this.#account = acc break diff --git a/dapp/src/utils/orangekit/ledger-live/tests/bitcoin-provider.test.ts b/dapp/src/utils/orangekit/ledger-live/tests/bitcoin-provider.test.ts index 58d1d0f89..6ba9cb41a 100644 --- a/dapp/src/utils/orangekit/ledger-live/tests/bitcoin-provider.test.ts +++ b/dapp/src/utils/orangekit/ledger-live/tests/bitcoin-provider.test.ts @@ -473,6 +473,8 @@ describe("AcreLedgerLiveBitcoinProvider", () => { }) }) + it("should get") + it("should get zero address for all accounts", () => { expect( mockedWalletApiClient.bitcoin.getAddress, diff --git a/dapp/src/wagmiConfig.ts b/dapp/src/wagmiConfig.ts index 19d1cf4e4..972a38fda 100644 --- a/dapp/src/wagmiConfig.ts +++ b/dapp/src/wagmiConfig.ts @@ -5,6 +5,7 @@ import { env } from "./constants" import { getLastUsedBtcAddress } from "./hooks/useLastUsedBtcAddress" import referralProgram, { EmbedApp } from "./utils/referralProgram" import { orangeKit } from "./utils" +import { AcreLedgerLiveBitcoinProviderOptions } from "./utils/orangekit/ledger-live/bitcoin-provider" const isTestnet = env.USE_TESTNET const CHAIN_ID = isTestnet ? sepolia.id : mainnet.id @@ -34,12 +35,19 @@ async function getWagmiConfig() { let createEmbedConnectorFn const embeddedApp = referralProgram.getEmbeddedApp() if (referralProgram.isEmbedApp(embeddedApp)) { + const lastUsedBtcAddress = getLastUsedBtcAddress() + const xpub = orangeKit.findXpubFromUrl(window.location.href) + const ledgerLiveConnectorOptions: AcreLedgerLiveBitcoinProviderOptions = + xpub + ? { tryConnectToAccountByXpub: xpub } + : { + tryConnectToAddress: lastUsedBtcAddress, + } + const orangeKitLedgerLiveConnector = orangeKit.getOrangeKitLedgerLiveConnector({ ...connectorConfig, - options: { - tryConnectToAddress: getLastUsedBtcAddress(), - }, + options: ledgerLiveConnectorOptions, }) const embedConnectorsMap: Record< From dbc653d49daae860190c1b3c132f963ab67497c4 Mon Sep 17 00:00:00 2001 From: Rafal Czajkowski Date: Wed, 27 Nov 2024 13:28:46 +0100 Subject: [PATCH 41/51] Update Ledger Live manifest Add the `bitcoin.getXpub` method to the `permissions` list. We use this method to connect to an account by `xpub`. --- dapp/manifests/ledger-live/ledger-live-manifest-development.json | 1 + dapp/manifests/ledger-live/ledger-live-manifest-mainnet.json | 1 + dapp/manifests/ledger-live/ledger-live-manifest-testnet.json | 1 + dapp/manifests/ledger-live/ledger-manifest-template.json | 1 + 4 files changed, 4 insertions(+) diff --git a/dapp/manifests/ledger-live/ledger-live-manifest-development.json b/dapp/manifests/ledger-live/ledger-live-manifest-development.json index 84e58fcad..bffaf7026 100644 --- a/dapp/manifests/ledger-live/ledger-live-manifest-development.json +++ b/dapp/manifests/ledger-live/ledger-live-manifest-development.json @@ -23,6 +23,7 @@ "account.list", "bitcoin.getAddress", "bitcoin.getPublicKey", + "bitcoin.getXPub", "transaction.signAndBroadcast", "custom.acre.messageSign", "custom.acre.transactionSignAndBroadcast" diff --git a/dapp/manifests/ledger-live/ledger-live-manifest-mainnet.json b/dapp/manifests/ledger-live/ledger-live-manifest-mainnet.json index 281992191..22f74bbc5 100644 --- a/dapp/manifests/ledger-live/ledger-live-manifest-mainnet.json +++ b/dapp/manifests/ledger-live/ledger-live-manifest-mainnet.json @@ -23,6 +23,7 @@ "account.list", "bitcoin.getAddress", "bitcoin.getPublicKey", + "bitcoin.getXPub", "transaction.signAndBroadcast", "custom.acre.messageSign", "custom.acre.transactionSignAndBroadcast" diff --git a/dapp/manifests/ledger-live/ledger-live-manifest-testnet.json b/dapp/manifests/ledger-live/ledger-live-manifest-testnet.json index 32dd4a45f..a6ea2019c 100644 --- a/dapp/manifests/ledger-live/ledger-live-manifest-testnet.json +++ b/dapp/manifests/ledger-live/ledger-live-manifest-testnet.json @@ -23,6 +23,7 @@ "account.list", "bitcoin.getAddress", "bitcoin.getPublicKey", + "bitcoin.getXPub", "transaction.signAndBroadcast", "custom.acre.messageSign", "custom.acre.transactionSignAndBroadcast" diff --git a/dapp/manifests/ledger-live/ledger-manifest-template.json b/dapp/manifests/ledger-live/ledger-manifest-template.json index e999601d2..980c407d2 100644 --- a/dapp/manifests/ledger-live/ledger-manifest-template.json +++ b/dapp/manifests/ledger-live/ledger-manifest-template.json @@ -23,6 +23,7 @@ "account.list", "bitcoin.getAddress", "bitcoin.getPublicKey", + "bitcoin.getXPub", "transaction.signAndBroadcast", "custom.acre.messageSign", "custom.acre.transactionSignAndBroadcast" From 68c5c994b1df7ed55c9595ebde1c0b7fafc200a0 Mon Sep 17 00:00:00 2001 From: Rafal Czajkowski Date: Wed, 27 Nov 2024 14:11:39 +0100 Subject: [PATCH 42/51] Improve the `ConnectWallet` component Keep the dropdown opene when the user selects `copy address` option. Extract shared component props to an array to not repeat the code. --- dapp/src/components/Header/ConnectWallet.tsx | 117 +++++++++---------- 1 file changed, 58 insertions(+), 59 deletions(-) diff --git a/dapp/src/components/Header/ConnectWallet.tsx b/dapp/src/components/Header/ConnectWallet.tsx index 32072522b..fad9aa380 100644 --- a/dapp/src/components/Header/ConnectWallet.tsx +++ b/dapp/src/components/Header/ConnectWallet.tsx @@ -69,6 +69,32 @@ export default function ConnectWallet() { ) } + const options = [ + { + id: "Copy", + icon: IconCopy, + label: hasCopied ? "Address copied" : "Copy Address", + onClick: onCopy, + isSupported: true, + closeOnSelect: false, + }, + { + id: "Change account", + icon: IconUserCode, + label: "Change account", + onClick: () => handleConnectWallet(true), + isSupported: isChangeAccountFeatureSupported(embeddedApp), + closeOnSelect: true, + }, + { + id: "Disconnect", + icon: IconLogout, + label: "Disconnect", + onClick: onDisconnect, + closeOnSelect: true, + isSupported: true, + }, + ] return isMobile ? ( @@ -83,29 +109,20 @@ export default function ConnectWallet() { {truncateAddress(address)} - } - onClick={onCopy} - > - {hasCopied ? "Address copied" : "Copy Address"} - - {isChangeAccountFeatureSupported(embeddedApp) && ( - } - onClick={() => handleConnectWallet(true)} - > - Change account - + {options.map( + (option) => + option.isSupported && ( + } + onClick={option.onClick} + > + {option.label} + + ), )} - } - onClick={onDisconnect} - > - Disconnect - )} @@ -147,44 +164,26 @@ export default function ConnectWallet() { spacing={1} divider={} > - - } - px={2} - boxSize={5} - onClick={onCopy} - /> - - - {isChangeAccountFeatureSupported(embeddedApp) && ( - - } - px={2} - boxSize={5} - onClick={() => handleConnectWallet(true)} - /> - + {options.map( + (option) => + option.isSupported && ( + + } + px={2} + boxSize={5} + onClick={option.onClick} + /> + + ), )} - - - } - px={2} - boxSize={5} - onClick={onDisconnect} - /> - From a69c04b4d62c504624dace04fd90e112a98f98f2 Mon Sep 17 00:00:00 2001 From: Rafal Czajkowski Date: Wed, 27 Nov 2024 14:28:16 +0100 Subject: [PATCH 43/51] Update breakpoints for modal styles --- .../TransactionModal/ResumeModal.tsx | 2 +- .../TransactionModal/SuccessModal.tsx | 2 +- .../WalletInteractionModal.tsx | 2 +- dapp/src/theme/Modal.ts | 25 ++++++++----------- dapp/src/theme/utils/semanticTokens.ts | 15 +++-------- 5 files changed, 17 insertions(+), 29 deletions(-) diff --git a/dapp/src/components/TransactionModal/ResumeModal.tsx b/dapp/src/components/TransactionModal/ResumeModal.tsx index bc2159265..3547673dc 100644 --- a/dapp/src/components/TransactionModal/ResumeModal.tsx +++ b/dapp/src/components/TransactionModal/ResumeModal.tsx @@ -22,7 +22,7 @@ export default function ResumeModal({ closeModal }: BaseModalProps) { return ( <> - + Paused diff --git a/dapp/src/components/TransactionModal/SuccessModal.tsx b/dapp/src/components/TransactionModal/SuccessModal.tsx index 5390a7e7f..7fa7f8d31 100644 --- a/dapp/src/components/TransactionModal/SuccessModal.tsx +++ b/dapp/src/components/TransactionModal/SuccessModal.tsx @@ -32,7 +32,7 @@ export default function SuccessModal({ type }: SuccessModalProps) { return ( <> - + {ACTION_FLOW_TYPES.UNSTAKE === type ? "Withdrawal initiated!" : "Deposit received!"} diff --git a/dapp/src/components/TransactionModal/WalletInteractionModal.tsx b/dapp/src/components/TransactionModal/WalletInteractionModal.tsx index 84a8469aa..e7add85ea 100644 --- a/dapp/src/components/TransactionModal/WalletInteractionModal.tsx +++ b/dapp/src/components/TransactionModal/WalletInteractionModal.tsx @@ -54,7 +54,7 @@ export default function WalletInteractionModal({ return ( <> {step === "opening-wallet" && } - + {header} diff --git a/dapp/src/theme/Modal.ts b/dapp/src/theme/Modal.ts index bd1846073..589d0f691 100644 --- a/dapp/src/theme/Modal.ts +++ b/dapp/src/theme/Modal.ts @@ -6,10 +6,7 @@ const baseStyleContainer = defineStyle({ }) const baseStyleDialog = defineStyle({ - marginTop: { - base: "var(--chakra-space-modal_shift)", - md: "var(--chakra-space-modal_shift_xl)", - }, + marginTop: { base: 12, sm: "var(--chakra-space-modal_shift)" }, marginBottom: 8, boxShadow: "none", borderRadius: "xl", @@ -19,10 +16,10 @@ const baseStyleDialog = defineStyle({ }) const baseCloseButton = defineStyle({ - top: { base: 3, md: -7 }, - right: { base: 3, md: -7 }, - boxSize: { md: 7 }, - rounded: { md: "100%" }, + top: { base: 3, sm: -7 }, + right: { base: 3, sm: -7 }, + boxSize: { sm: 7 }, + rounded: { sm: "100%" }, bg: "opacity.white.5", _hover: { @@ -41,8 +38,8 @@ const baseStyleHeader = defineStyle({ fontSize: "xl", lineHeight: "xl", fontWeight: "bold", - pt: { md: 10 }, - px: { md: 10 }, + pt: { sm: 10 }, + px: { sm: 10 }, mb: 8, }) @@ -54,15 +51,15 @@ const baseStyleBody = defineStyle({ alignItems: "center", gap: 6, pt: 0, - px: { base: 0, md: 8 }, - pb: { base: 0, md: 10 }, + px: { base: 0, sm: 8 }, + pb: { base: 0, sm: 10 }, }) const baseStyleFooter = defineStyle({ flexDirection: "column", gap: 6, - px: { base: 0, md: 8 }, - pb: { base: 0, md: 10 }, + px: { base: 0, sm: 8 }, + pb: { base: 0, sm: 10 }, }) const multiStyleConfig = createMultiStyleConfigHelpers(parts.keys) diff --git a/dapp/src/theme/utils/semanticTokens.ts b/dapp/src/theme/utils/semanticTokens.ts index dfd56d42b..8ad1298ba 100644 --- a/dapp/src/theme/utils/semanticTokens.ts +++ b/dapp/src/theme/utils/semanticTokens.ts @@ -1,17 +1,8 @@ -const headerHeight = 28 -const headerHeightXl = 36 - -const modalShiftToHeaderHeight = { - [headerHeight]: 28, - [headerHeightXl]: "9.25rem", -} - export const semanticTokens = { space: { - header_height: headerHeight, - header_height_xl: headerHeightXl, - modal_shift: modalShiftToHeaderHeight[headerHeight], - modal_shift_xl: modalShiftToHeaderHeight[headerHeightXl], + header_height: 28, + header_height_xl: 36, + modal_shift: "9.75rem", // 156px dashboard_card_padding: 5, }, sizes: { From 34a33d530d86e0f32dd10b0f431fa5a6dec2ffe8 Mon Sep 17 00:00:00 2001 From: Rafal Czajkowski Date: Wed, 27 Nov 2024 16:38:18 +0100 Subject: [PATCH 44/51] Remove unnecessary `it` in test --- .../utils/orangekit/ledger-live/tests/bitcoin-provider.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/dapp/src/utils/orangekit/ledger-live/tests/bitcoin-provider.test.ts b/dapp/src/utils/orangekit/ledger-live/tests/bitcoin-provider.test.ts index 6ba9cb41a..58d1d0f89 100644 --- a/dapp/src/utils/orangekit/ledger-live/tests/bitcoin-provider.test.ts +++ b/dapp/src/utils/orangekit/ledger-live/tests/bitcoin-provider.test.ts @@ -473,8 +473,6 @@ describe("AcreLedgerLiveBitcoinProvider", () => { }) }) - it("should get") - it("should get zero address for all accounts", () => { expect( mockedWalletApiClient.bitcoin.getAddress, From 552990dcd0acfd54c1633f914efd3933d0a7d7b6 Mon Sep 17 00:00:00 2001 From: Jakub Date: Wed, 27 Nov 2024 22:35:16 +0100 Subject: [PATCH 45/51] Log connection error We are now logging connection errors to the console. This will help us debug connection issues, as the error will be reported to Sentry. We're handling only the `DEFAULT` error type, as the other types are reported to the user in a modal. --- .../components/ConnectWalletModal/ConnectWalletButton.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dapp/src/components/ConnectWalletModal/ConnectWalletButton.tsx b/dapp/src/components/ConnectWalletModal/ConnectWalletButton.tsx index 0747fdc8e..8b12b6236 100644 --- a/dapp/src/components/ConnectWalletModal/ConnectWalletButton.tsx +++ b/dapp/src/components/ConnectWalletModal/ConnectWalletButton.tsx @@ -129,6 +129,11 @@ export default function ConnectWalletButton({ }, onError: (error: OrangeKitError) => { const errorData = orangeKit.parseOrangeKitConnectionError(error) + + if (errorData === CONNECTION_ERRORS.DEFAULT) { + console.error("Failed to connect", error) + } + setConnectionError(errorData) }, }) From eb17acecc4e15221fdaa3ac3f9ef83dcc54bc415 Mon Sep 17 00:00:00 2001 From: Jakub Date: Wed, 27 Nov 2024 23:26:09 +0100 Subject: [PATCH 46/51] Set Sentry user id to hashed identifier We calculate the ID of the user by hashing the address. This way we won't store any sensitive information in Sentry. --- dapp/package.json | 2 ++ dapp/src/sentry.test.ts | 38 +++++++++++++++++++++++++ dapp/src/{sentry/index.ts => sentry.ts} | 23 ++++++++++++++- 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 dapp/src/sentry.test.ts rename dapp/src/{sentry/index.ts => sentry.ts} (52%) diff --git a/dapp/package.json b/dapp/package.json index b384d7b43..9914048db 100644 --- a/dapp/package.json +++ b/dapp/package.json @@ -35,6 +35,7 @@ "@tanstack/react-query-devtools": "^5.49.2", "axios": "^1.6.7", "bignumber.js": "^9.1.2", + "crypto-js": "^4.2.0", "ethers": "^6.10.0", "formik": "^2.4.5", "framer-motion": "^10.16.5", @@ -52,6 +53,7 @@ "devDependencies": { "@sentry/vite-plugin": "^2.22.5", "@thesis-co/eslint-config": "github:thesis/eslint-config#7b9bc8c", + "@types/crypto-js": "^4.2.2", "@types/luxon": "^3.4.2", "@types/react": "^18.2.38", "@types/react-dom": "^18.2.17", diff --git a/dapp/src/sentry.test.ts b/dapp/src/sentry.test.ts new file mode 100644 index 000000000..7543d8d1d --- /dev/null +++ b/dapp/src/sentry.test.ts @@ -0,0 +1,38 @@ +import { describe, expect, it, vi } from "vitest" +import * as Sentry from "@sentry/react" +import sentry from "./sentry" + +describe("sentry", () => { + describe("setUser", () => { + vi.mock("@sentry/react") + + const testCases = [ + { bitcoinAddress: undefined, expectedResult: null }, + { bitcoinAddress: "", expectedResult: null }, + { bitcoinAddress: " ", expectedResult: null }, + { + bitcoinAddress: "17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem", + expectedResult: { id: "1f520a9757" }, + }, + { + bitcoinAddress: "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4", + expectedResult: { id: "6cd42dab02" }, + }, + { + bitcoinAddress: "BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4", + expectedResult: { id: "6cd42dab02" }, + }, + ] + + describe.each(testCases)( + "when address is $bitcoinAddress", + ({ bitcoinAddress, expectedResult }) => { + it("should set expected user in Sentry", () => { + sentry.setUser(bitcoinAddress) + + expect(Sentry.setUser).toHaveBeenCalledWith(expectedResult) + }) + }, + ) + }) +}) diff --git a/dapp/src/sentry/index.ts b/dapp/src/sentry.ts similarity index 52% rename from dapp/src/sentry/index.ts rename to dapp/src/sentry.ts index 2a1bfb988..6217c7ea0 100644 --- a/dapp/src/sentry/index.ts +++ b/dapp/src/sentry.ts @@ -1,4 +1,5 @@ import * as Sentry from "@sentry/react" +import * as CryptoJS from "crypto-js" const initialize = (dsn: string) => { Sentry.init({ @@ -17,8 +18,28 @@ const initialize = (dsn: string) => { }) } +/** + * Sets the user in Sentry with an ID from hashed Bitcoin address. + * The Bitcoin address is first converted to lowercase and then hashed using SHA-256. + * The resulting hash is then converted to a hexadecimal string and the first 10 + * characters are set as the user ID. + * + * @param bitcoinAddress - The Bitcoin address of the user. If undefined, the user + * is set to null in Sentry. + */ const setUser = (bitcoinAddress: string | undefined) => { - Sentry.setUser(bitcoinAddress ? { id: bitcoinAddress } : null) + if (!bitcoinAddress) { + Sentry.setUser(null) + return + } + + const hashedBitcoinAddress = CryptoJS.SHA256( + bitcoinAddress.toLowerCase(), + ).toString(CryptoJS.enc.Hex) + + const id = hashedBitcoinAddress.slice(0, 10) + + Sentry.setUser({ id }) } const captureException = (exception: unknown) => From 10366af8ccdc51cd5c23d0b7258065d6ac99e845 Mon Sep 17 00:00:00 2001 From: Jakub Date: Thu, 28 Nov 2024 00:41:44 +0100 Subject: [PATCH 47/51] Add pnpm-lock.yaml --- pnpm-lock.yaml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 53c684f24..9ce741fed 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -74,6 +74,9 @@ importers: bignumber.js: specifier: ^9.1.2 version: 9.1.2 + crypto-js: + specifier: ^4.2.0 + version: 4.2.0 ethers: specifier: ^6.10.0 version: 6.13.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) @@ -120,6 +123,9 @@ importers: '@thesis-co/eslint-config': specifier: github:thesis/eslint-config#7b9bc8c version: https://codeload.github.com/thesis/eslint-config/tar.gz/7b9bc8c(eslint@8.57.0)(prettier@3.3.2)(typescript@5.4.5) + '@types/crypto-js': + specifier: ^4.2.2 + version: 4.2.2 '@types/luxon': specifier: ^3.4.2 version: 3.4.2 @@ -3557,6 +3563,9 @@ packages: '@types/country-data@0.0.0': resolution: {integrity: sha512-lIxCk6G7AwmUagQ4gIQGxUBnvAq664prFD9nSAz6dgd1XmBXBtZABV/op+QsJsIyaP1GZsf/iXhYKHX3azSRCw==} + '@types/crypto-js@4.2.2': + resolution: {integrity: sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==} + '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} @@ -5157,6 +5166,9 @@ packages: crypto-js@3.3.0: resolution: {integrity: sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q==} + crypto-js@4.2.0: + resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} + css-box-model@1.2.1: resolution: {integrity: sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==} @@ -16083,6 +16095,8 @@ snapshots: '@types/country-data@0.0.0': {} + '@types/crypto-js@4.2.2': {} + '@types/debug@4.1.12': dependencies: '@types/ms': 0.7.34 @@ -18477,6 +18491,8 @@ snapshots: crypto-js@3.3.0: {} + crypto-js@4.2.0: {} + css-box-model@1.2.1: dependencies: tiny-invariant: 1.3.3 From 6f92877d7db605e93c9523bd1c6f98b6554e01c8 Mon Sep 17 00:00:00 2001 From: Rafal Czajkowski Date: Thu, 28 Nov 2024 12:36:59 +0100 Subject: [PATCH 48/51] Improve padding in modal component on mobile --- dapp/src/components/MezoBeehiveModal.tsx | 2 +- dapp/src/theme/Modal.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dapp/src/components/MezoBeehiveModal.tsx b/dapp/src/components/MezoBeehiveModal.tsx index ccc88a5e0..18ca145d8 100644 --- a/dapp/src/components/MezoBeehiveModal.tsx +++ b/dapp/src/components/MezoBeehiveModal.tsx @@ -42,7 +42,7 @@ function MezoBeehiveModalBase() { - + {data && ( diff --git a/dapp/src/theme/Modal.ts b/dapp/src/theme/Modal.ts index 589d0f691..5008352a8 100644 --- a/dapp/src/theme/Modal.ts +++ b/dapp/src/theme/Modal.ts @@ -10,7 +10,7 @@ const baseStyleDialog = defineStyle({ marginBottom: 8, boxShadow: "none", borderRadius: "xl", - p: { base: 5 }, + p: { base: 5, sm: 0 }, bg: "gold.100", border: "none", }) @@ -40,7 +40,7 @@ const baseStyleHeader = defineStyle({ fontWeight: "bold", pt: { sm: 10 }, px: { sm: 10 }, - mb: 8, + pb: 8, }) const baseStyleBody = defineStyle({ From 41c0fd96f70b983486ade2b3048adc87ee9fcc02 Mon Sep 17 00:00:00 2001 From: Rafal Czajkowski Date: Thu, 28 Nov 2024 12:50:21 +0100 Subject: [PATCH 49/51] Do not change the modal width There is no need to change the modal width - we should use the previous value. --- dapp/src/theme/Modal.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dapp/src/theme/Modal.ts b/dapp/src/theme/Modal.ts index 5008352a8..506c7d038 100644 --- a/dapp/src/theme/Modal.ts +++ b/dapp/src/theme/Modal.ts @@ -88,7 +88,7 @@ const sizeXl = multiStyleConfig.definePartsStyle({ }) const sizeLg = multiStyleConfig.definePartsStyle({ - dialog: { w: { xs: "95%" } }, + dialog: { w: "30rem" }, }) const sizeFull = multiStyleConfig.definePartsStyle({ From 679db3f05a26befb392b3ab2cdfb77eed39155d7 Mon Sep 17 00:00:00 2001 From: Jakub Date: Thu, 28 Nov 2024 12:50:53 +0100 Subject: [PATCH 50/51] Use existing ethers library to calculate hash We don't need to introduce another crypto-js library to calculate the hash. We can use the existing ethers library. --- dapp/package.json | 2 -- dapp/src/sentry.ts | 10 ++++------ pnpm-lock.yaml | 16 ---------------- 3 files changed, 4 insertions(+), 24 deletions(-) diff --git a/dapp/package.json b/dapp/package.json index 9914048db..b384d7b43 100644 --- a/dapp/package.json +++ b/dapp/package.json @@ -35,7 +35,6 @@ "@tanstack/react-query-devtools": "^5.49.2", "axios": "^1.6.7", "bignumber.js": "^9.1.2", - "crypto-js": "^4.2.0", "ethers": "^6.10.0", "formik": "^2.4.5", "framer-motion": "^10.16.5", @@ -53,7 +52,6 @@ "devDependencies": { "@sentry/vite-plugin": "^2.22.5", "@thesis-co/eslint-config": "github:thesis/eslint-config#7b9bc8c", - "@types/crypto-js": "^4.2.2", "@types/luxon": "^3.4.2", "@types/react": "^18.2.38", "@types/react-dom": "^18.2.17", diff --git a/dapp/src/sentry.ts b/dapp/src/sentry.ts index 6217c7ea0..f3707ede4 100644 --- a/dapp/src/sentry.ts +++ b/dapp/src/sentry.ts @@ -1,5 +1,5 @@ import * as Sentry from "@sentry/react" -import * as CryptoJS from "crypto-js" +import { sha256, toUtf8Bytes } from "ethers" const initialize = (dsn: string) => { Sentry.init({ @@ -33,11 +33,9 @@ const setUser = (bitcoinAddress: string | undefined) => { return } - const hashedBitcoinAddress = CryptoJS.SHA256( - bitcoinAddress.toLowerCase(), - ).toString(CryptoJS.enc.Hex) - - const id = hashedBitcoinAddress.slice(0, 10) + const hashedBitcoinAddress = sha256(toUtf8Bytes(bitcoinAddress.toLowerCase())) + // Remove the 0x prefix and take the first 10 characters. + const id = hashedBitcoinAddress.slice(2, 12) Sentry.setUser({ id }) } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9ce741fed..53c684f24 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -74,9 +74,6 @@ importers: bignumber.js: specifier: ^9.1.2 version: 9.1.2 - crypto-js: - specifier: ^4.2.0 - version: 4.2.0 ethers: specifier: ^6.10.0 version: 6.13.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) @@ -123,9 +120,6 @@ importers: '@thesis-co/eslint-config': specifier: github:thesis/eslint-config#7b9bc8c version: https://codeload.github.com/thesis/eslint-config/tar.gz/7b9bc8c(eslint@8.57.0)(prettier@3.3.2)(typescript@5.4.5) - '@types/crypto-js': - specifier: ^4.2.2 - version: 4.2.2 '@types/luxon': specifier: ^3.4.2 version: 3.4.2 @@ -3563,9 +3557,6 @@ packages: '@types/country-data@0.0.0': resolution: {integrity: sha512-lIxCk6G7AwmUagQ4gIQGxUBnvAq664prFD9nSAz6dgd1XmBXBtZABV/op+QsJsIyaP1GZsf/iXhYKHX3azSRCw==} - '@types/crypto-js@4.2.2': - resolution: {integrity: sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==} - '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} @@ -5166,9 +5157,6 @@ packages: crypto-js@3.3.0: resolution: {integrity: sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q==} - crypto-js@4.2.0: - resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} - css-box-model@1.2.1: resolution: {integrity: sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==} @@ -16095,8 +16083,6 @@ snapshots: '@types/country-data@0.0.0': {} - '@types/crypto-js@4.2.2': {} - '@types/debug@4.1.12': dependencies: '@types/ms': 0.7.34 @@ -18491,8 +18477,6 @@ snapshots: crypto-js@3.3.0: {} - crypto-js@4.2.0: {} - css-box-model@1.2.1: dependencies: tiny-invariant: 1.3.3 From b37293eec0dfc75fb88b8d8fc3c3c344d316f4fc Mon Sep 17 00:00:00 2001 From: Rafal Czajkowski Date: Thu, 28 Nov 2024 13:26:59 +0100 Subject: [PATCH 51/51] Update `ModalBody` horizontal padding The `ModalHeader` and `ModalBoyd` components should have the same horizontal padding. --- dapp/src/components/WelcomeModal.tsx | 2 +- dapp/src/theme/Modal.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dapp/src/components/WelcomeModal.tsx b/dapp/src/components/WelcomeModal.tsx index d29d17fdf..b68a6ce75 100644 --- a/dapp/src/components/WelcomeModal.tsx +++ b/dapp/src/components/WelcomeModal.tsx @@ -136,7 +136,7 @@ function WelcomeModalBase({ closeModal }: BaseModalProps) { {activeStepData.title} - + {activeStepData.content(embeddedApp)}