From 8f4b70085d9d7da54e7a086a01c901e5c0ad2929 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 6 Dec 2023 11:01:17 +0100 Subject: [PATCH 1/9] Disabling the unnecessary eslint rule --- dapp/.eslintrc | 11 ++++++++++- dapp/src/components/Header/ConnectWallet.tsx | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/dapp/.eslintrc b/dapp/.eslintrc index 441891d36..c6a162b85 100644 --- a/dapp/.eslintrc +++ b/dapp/.eslintrc @@ -3,6 +3,15 @@ "extends": ["@thesis-co"], "rules": { "import/no-extraneous-dependencies": "off", - "import/prefer-default-export": "off" + "import/prefer-default-export": "off", + // TypeScript allows us to declare props that are non-optional internally + // but are interpreted as optional externally if they have defaultProps + // defined; the following two adjustments disable eslint-plugin-react + // checks that predate this ability for TS and that no longer apply. + "react/default-props-match-prop-types": [ + 2, + { "allowRequiredDefaults": true } + ], + "react/require-default-props": [0] } } diff --git a/dapp/src/components/Header/ConnectWallet.tsx b/dapp/src/components/Header/ConnectWallet.tsx index 8b35a010b..a5c3ef3bb 100644 --- a/dapp/src/components/Header/ConnectWallet.tsx +++ b/dapp/src/components/Header/ConnectWallet.tsx @@ -20,7 +20,7 @@ import { formatSatoshiAmount, truncateAddress } from "../../utils" export type ConnectButtonsProps = { leftIcon: typeof Icon rightIcon: typeof Icon - account: Account | undefined + account?: Account requestAccount: () => Promise } From d9d70ae7b01fdc2a23d383ff333567f8f48bdc09 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 6 Dec 2023 11:54:10 +0100 Subject: [PATCH 2/9] Initialization of the staking flow --- dapp/src/DApp.tsx | 14 ++-- dapp/src/components/Header/index.tsx | 4 +- dapp/src/components/ModalOverlay/index.tsx | 41 +++++++++++ dapp/src/components/Modals/BaseModal.tsx | 23 ++++++ .../components/Modals/ConnectWalletModal.tsx | 44 ++++++++++++ .../Modals/StakingOverviewModal.tsx | 67 ++++++++++++++++++ .../components/Overview/PositionDetails.tsx | 49 +++++++------ dapp/src/components/Staking/index.tsx | 28 ++++++++ dapp/src/contexts/StakingFlowContext.tsx | 42 +++++++++++ dapp/src/contexts/WalletContext.tsx | 11 +-- dapp/src/contexts/index.tsx | 1 + dapp/src/hooks/index.ts | 1 + dapp/src/hooks/useRequestBitcoinAccount.ts | 6 +- dapp/src/hooks/useRequestEthereumAccount.ts | 6 +- dapp/src/hooks/useStakingFlowContext.ts | 14 ++++ dapp/src/static/images/ConnectBTCAccount.png | Bin 0 -> 5287 bytes dapp/src/types/index.ts | 1 + dapp/src/types/staking.ts | 1 + 18 files changed, 317 insertions(+), 36 deletions(-) create mode 100644 dapp/src/components/ModalOverlay/index.tsx create mode 100644 dapp/src/components/Modals/BaseModal.tsx create mode 100644 dapp/src/components/Modals/ConnectWalletModal.tsx create mode 100644 dapp/src/components/Modals/StakingOverviewModal.tsx create mode 100644 dapp/src/components/Staking/index.tsx create mode 100644 dapp/src/contexts/StakingFlowContext.tsx create mode 100644 dapp/src/hooks/useStakingFlowContext.ts create mode 100644 dapp/src/static/images/ConnectBTCAccount.png create mode 100644 dapp/src/types/staking.ts diff --git a/dapp/src/DApp.tsx b/dapp/src/DApp.tsx index 085b6fbe8..d1d38a8bd 100644 --- a/dapp/src/DApp.tsx +++ b/dapp/src/DApp.tsx @@ -2,7 +2,11 @@ import React from "react" import { ChakraProvider } from "@chakra-ui/react" import { useDetectThemeMode } from "./hooks" import theme from "./theme" -import { LedgerWalletAPIProvider, WalletContextProvider } from "./contexts" +import { + LedgerWalletAPIProvider, + StakingFlowProvider, + WalletContextProvider, +} from "./contexts" import Header from "./components/Header" import Overview from "./components/Overview" @@ -23,9 +27,11 @@ function DAppProviders() { return ( - - - + + + + + ) diff --git a/dapp/src/components/Header/index.tsx b/dapp/src/components/Header/index.tsx index 838ed37b2..d78d97ef8 100644 --- a/dapp/src/components/Header/index.tsx +++ b/dapp/src/components/Header/index.tsx @@ -2,9 +2,11 @@ import React from "react" import { Flex } from "@chakra-ui/react" import ConnectWallet from "./ConnectWallet" +export const HEADER_HEIGHT = 24 + export default function Header() { return ( - + ) diff --git a/dapp/src/components/ModalOverlay/index.tsx b/dapp/src/components/ModalOverlay/index.tsx new file mode 100644 index 000000000..9ca30d1f1 --- /dev/null +++ b/dapp/src/components/ModalOverlay/index.tsx @@ -0,0 +1,41 @@ +import React, { useEffect, useState } from "react" +import { Box, useColorModeValue } from "@chakra-ui/react" +import { useStakingFlowContext } from "../../hooks" + +const DELAY = 300 + +export default function ModalOverlay({ marginTop }: { marginTop?: number }) { + const { modalType } = useStakingFlowContext() + const [showOverlay, setShowOverlay] = useState(!modalType) + + useEffect(() => { + const timeout = setTimeout( + () => { + setShowOverlay(!!modalType) + }, + // When the modal opens, we should show the sidebar without delay. + // However, when the modal disappears, the overlay should disappear with some delay. + modalType ? 0 : DELAY, + ) + return () => clearTimeout(timeout) + }, [modalType]) + + return ( + + ) +} diff --git a/dapp/src/components/Modals/BaseModal.tsx b/dapp/src/components/Modals/BaseModal.tsx new file mode 100644 index 000000000..1f98f4345 --- /dev/null +++ b/dapp/src/components/Modals/BaseModal.tsx @@ -0,0 +1,23 @@ +import React from "react" +import { Modal, ModalCloseButton, ModalContent } from "@chakra-ui/react" +import { useStakingFlowContext } from "../../hooks" +import { HEADER_HEIGHT } from "../Header" + +export default function BaseModal({ children }: { children: React.ReactNode }) { + const { closeModal } = useStakingFlowContext() + + return ( + + + + {children} + + + ) +} diff --git a/dapp/src/components/Modals/ConnectWalletModal.tsx b/dapp/src/components/Modals/ConnectWalletModal.tsx new file mode 100644 index 000000000..5ca953960 --- /dev/null +++ b/dapp/src/components/Modals/ConnectWalletModal.tsx @@ -0,0 +1,44 @@ +import React from "react" +import { + Button, + Image, + ModalBody, + ModalFooter, + ModalHeader, + VStack, + Text, +} from "@chakra-ui/react" +import { useRequestBitcoinAccount } from "../../hooks" +import BaseModal from "./BaseModal" +import ConnectBTCAccount from "../../static/images/ConnectBTCAccount.png" + +export default function ConnectWalletModal() { + const { requestAccount } = useRequestBitcoinAccount() + + return ( + + + Bitcoin account not installed + + + + + + Bitcoin account is required to make transactions for depositing and + staking your BTC. + + + + + + + + ) +} diff --git a/dapp/src/components/Modals/StakingOverviewModal.tsx b/dapp/src/components/Modals/StakingOverviewModal.tsx new file mode 100644 index 000000000..e7cbcddb2 --- /dev/null +++ b/dapp/src/components/Modals/StakingOverviewModal.tsx @@ -0,0 +1,67 @@ +import React from "react" +import { + Button, + Flex, + ModalBody, + ModalFooter, + ModalHeader, + Step, + StepDescription, + StepIndicator, + StepNumber, + StepSeparator, + StepTitle, + Stepper, +} from "@chakra-ui/react" +import { useStakingFlowContext } from "../../hooks" +import BaseModal from "./BaseModal" + +const STEPS = [ + { + title: "Sign message", + description: + "You will sign a gas-free Ethereum message to indicate the address where you'd like to get your stBTC liquid staking token.", + }, + { + title: "Deposit BTC", + description: + "You will make a Bitcoin transaction to deposit and stake your BTC.", + }, +] + +export default function StakingOverviewModal() { + const { closeModal } = useStakingFlowContext() + + return ( + + Staking overview + + + {STEPS.map((step) => ( + + + + + + {step.title} + {step.description} + + + + ))} + + + + + + + ) +} diff --git a/dapp/src/components/Overview/PositionDetails.tsx b/dapp/src/components/Overview/PositionDetails.tsx index 972db661f..cfe51119c 100644 --- a/dapp/src/components/Overview/PositionDetails.tsx +++ b/dapp/src/components/Overview/PositionDetails.tsx @@ -10,34 +10,41 @@ import { } from "@chakra-ui/react" import { BITCOIN, USD } from "../../constants" import { Info } from "../../static/icons" +import Staking from "../Staking" +import { useStakingFlowContext } from "../../hooks" export default function PositionDetails() { + const { setModalType } = useStakingFlowContext() + return ( - - - Your positions - - - 34.75 - {BITCOIN.symbol} - - + <> + + + Your positions + - 1.245.148,1 - {USD.symbol} + 34.75 + {BITCOIN.symbol} - {/* TODO: Add correct text for tooltip */} - - - + + + 1.245.148,1 + {USD.symbol} + + {/* TODO: Add correct text for tooltip */} + + + + + + {/* TODO: Handle click actions */} + + + - - {/* TODO: Handle click actions */} - - - - + + ) } diff --git a/dapp/src/components/Staking/index.tsx b/dapp/src/components/Staking/index.tsx new file mode 100644 index 000000000..b4e56103b --- /dev/null +++ b/dapp/src/components/Staking/index.tsx @@ -0,0 +1,28 @@ +import React from "react" +import ConnectWalletModal from "../Modals/ConnectWalletModal" +import StakingOverviewModal from "../Modals/StakingOverviewModal" +import { useStakingFlowContext, useWalletContext } from "../../hooks" +import ModalOverlay from "../ModalOverlay" +import { HEADER_HEIGHT } from "../Header" + +function Modal() { + const { modalType } = useStakingFlowContext() + const { btcAccount } = useWalletContext() + + if (!modalType) return null + + if (!btcAccount) return + + if (modalType === "overview") return +} + +export default function Staking() { + return ( + <> + + {/* The user has several modals in a flow. + Let's use our own modal overlay to prevent the background flickering effect. */} + + + ) +} diff --git a/dapp/src/contexts/StakingFlowContext.tsx b/dapp/src/contexts/StakingFlowContext.tsx new file mode 100644 index 000000000..a58446787 --- /dev/null +++ b/dapp/src/contexts/StakingFlowContext.tsx @@ -0,0 +1,42 @@ +import React, { createContext, useCallback, useMemo, useState } from "react" +import { ModalType } from "../types" + +type StakingFlowContextValue = { + modalType: ModalType | undefined + closeModal: () => void + setModalType: React.Dispatch> +} + +export const StakingFlowContext = createContext({ + modalType: undefined, + setModalType: () => {}, + closeModal: () => {}, +}) + +export function StakingFlowProvider({ + children, +}: { + children: React.ReactNode +}): React.ReactElement { + const [modalType, setModalType] = useState(undefined) + + const closeModal = useCallback(() => { + setModalType(undefined) + }, []) + + const contextValue: StakingFlowContextValue = + useMemo( + () => ({ + modalType, + closeModal, + setModalType, + }), + [modalType, closeModal], + ) + + return ( + + {children} + + ) +} diff --git a/dapp/src/contexts/WalletContext.tsx b/dapp/src/contexts/WalletContext.tsx index f327ce0bd..63fb3faba 100644 --- a/dapp/src/contexts/WalletContext.tsx +++ b/dapp/src/contexts/WalletContext.tsx @@ -8,9 +8,12 @@ type WalletContextValue = { setEthAccount: React.Dispatch> } -export const WalletContext = createContext( - undefined, -) +export const WalletContext = createContext({ + ethAccount: undefined, + btcAccount: undefined, + setEthAccount: () => {}, + setBtcAccount: () => {}, +}) export function WalletContextProvider({ children, @@ -27,7 +30,7 @@ export function WalletContextProvider({ ethAccount, setEthAccount, }), - [btcAccount, setBtcAccount, ethAccount, setEthAccount], + [btcAccount, ethAccount], ) return ( diff --git a/dapp/src/contexts/index.tsx b/dapp/src/contexts/index.tsx index 3ea3058ed..9271773c0 100644 --- a/dapp/src/contexts/index.tsx +++ b/dapp/src/contexts/index.tsx @@ -1,2 +1,3 @@ export * from "./WalletContext" export * from "./LedgerWalletAPIProvider" +export * from "./StakingFlowContext" diff --git a/dapp/src/hooks/index.ts b/dapp/src/hooks/index.ts index 038388476..b12025abb 100644 --- a/dapp/src/hooks/index.ts +++ b/dapp/src/hooks/index.ts @@ -2,3 +2,4 @@ export * from "./useDetectThemeMode" export * from "./useRequestBitcoinAccount" export * from "./useRequestEthereumAccount" export * from "./useWalletContext" +export * from "./useStakingFlowContext" diff --git a/dapp/src/hooks/useRequestBitcoinAccount.ts b/dapp/src/hooks/useRequestBitcoinAccount.ts index 971a3f9ef..b9cce07c2 100644 --- a/dapp/src/hooks/useRequestBitcoinAccount.ts +++ b/dapp/src/hooks/useRequestBitcoinAccount.ts @@ -5,12 +5,12 @@ import { UseRequestAccountReturn } from "../types" import { WalletContext } from "../contexts" export function useRequestBitcoinAccount(): UseRequestAccountReturn { - const walletContext = useContext(WalletContext) + const { setBtcAccount } = useContext(WalletContext) const { account, requestAccount } = useRequestAccount() useEffect(() => { - walletContext?.setBtcAccount(account || undefined) - }, [account, walletContext]) + setBtcAccount(account || undefined) + }, [account, setBtcAccount]) const requestBitcoinAccount = useCallback(async () => { await requestAccount({ currencyIds: [CURRENCY_ID_BITCOIN] }) diff --git a/dapp/src/hooks/useRequestEthereumAccount.ts b/dapp/src/hooks/useRequestEthereumAccount.ts index ebeb1f268..c780aea20 100644 --- a/dapp/src/hooks/useRequestEthereumAccount.ts +++ b/dapp/src/hooks/useRequestEthereumAccount.ts @@ -5,12 +5,12 @@ import { UseRequestAccountReturn } from "../types" import { WalletContext } from "../contexts" export function useRequestEthereumAccount(): UseRequestAccountReturn { - const walletContext = useContext(WalletContext) + const { setEthAccount } = useContext(WalletContext) const { account, requestAccount } = useRequestAccount() useEffect(() => { - walletContext?.setEthAccount(account || undefined) - }, [account, walletContext]) + setEthAccount(account || undefined) + }, [account, setEthAccount]) const requestEthereumAccount = useCallback(async () => { await requestAccount({ currencyIds: [CURRENCY_ID_ETHEREUM] }) diff --git a/dapp/src/hooks/useStakingFlowContext.ts b/dapp/src/hooks/useStakingFlowContext.ts new file mode 100644 index 000000000..870e15f71 --- /dev/null +++ b/dapp/src/hooks/useStakingFlowContext.ts @@ -0,0 +1,14 @@ +import { useContext } from "react" +import { StakingFlowContext } from "../contexts" + +export function useStakingFlowContext() { + const context = useContext(StakingFlowContext) + + if (!context) { + throw new Error( + "StakingFlowContext used outside of StakingFlowContext component", + ) + } + + return context +} diff --git a/dapp/src/static/images/ConnectBTCAccount.png b/dapp/src/static/images/ConnectBTCAccount.png new file mode 100644 index 0000000000000000000000000000000000000000..deff3c0cc0415a029d766cf59af2a38af1490a55 GIT binary patch literal 5287 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 literal 0 HcmV?d00001 diff --git a/dapp/src/types/index.ts b/dapp/src/types/index.ts index 1e77e81e7..32b259c7f 100644 --- a/dapp/src/types/index.ts +++ b/dapp/src/types/index.ts @@ -1,2 +1,3 @@ export * from "./ledger-live-app" export * from "./currency" +export * from "./staking" diff --git a/dapp/src/types/staking.ts b/dapp/src/types/staking.ts new file mode 100644 index 000000000..38c5d8098 --- /dev/null +++ b/dapp/src/types/staking.ts @@ -0,0 +1 @@ +export type ModalType = "overview" | "stake" From 0df5493307b7e8283c0a30e7edc17e95c0669784 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 6 Dec 2023 12:01:51 +0100 Subject: [PATCH 3/9] Add a sidebar for docs drawer --- dapp/src/DApp.tsx | 9 +++-- dapp/src/components/DocsDrawer/index.tsx | 27 +++++++++++++++ dapp/src/components/Sidebar/index.tsx | 31 +++++++++++++++++ dapp/src/components/Staking/index.tsx | 2 ++ dapp/src/contexts/DocsDrawerContext.tsx | 44 ++++++++++++++++++++++++ dapp/src/contexts/index.tsx | 1 + dapp/src/hooks/index.ts | 1 + dapp/src/hooks/useDocsDrawerContext.ts | 14 ++++++++ dapp/src/theme/Drawer.ts | 11 ++++++ dapp/src/theme/index.ts | 5 ++- dapp/src/theme/utils/index.ts | 1 + dapp/src/theme/utils/zIndices.ts | 17 +++++++++ 12 files changed, 159 insertions(+), 4 deletions(-) create mode 100644 dapp/src/components/DocsDrawer/index.tsx create mode 100644 dapp/src/components/Sidebar/index.tsx create mode 100644 dapp/src/contexts/DocsDrawerContext.tsx create mode 100644 dapp/src/hooks/useDocsDrawerContext.ts create mode 100644 dapp/src/theme/Drawer.ts create mode 100644 dapp/src/theme/utils/zIndices.ts diff --git a/dapp/src/DApp.tsx b/dapp/src/DApp.tsx index d1d38a8bd..d87e33642 100644 --- a/dapp/src/DApp.tsx +++ b/dapp/src/DApp.tsx @@ -6,6 +6,7 @@ import { LedgerWalletAPIProvider, StakingFlowProvider, WalletContextProvider, + DocsDrawerContextProvider, } from "./contexts" import Header from "./components/Header" import Overview from "./components/Overview" @@ -28,9 +29,11 @@ function DAppProviders() { - - - + + + + + diff --git a/dapp/src/components/DocsDrawer/index.tsx b/dapp/src/components/DocsDrawer/index.tsx new file mode 100644 index 000000000..2aeb2a0b2 --- /dev/null +++ b/dapp/src/components/DocsDrawer/index.tsx @@ -0,0 +1,27 @@ +import React from "react" +import { + Drawer, + DrawerBody, + DrawerContent, + Text, + DrawerOverlay, + useColorModeValue, +} from "@chakra-ui/react" +import { useDocsDrawerContext } from "../../hooks" + +export default function DocsDrawer() { + const { isOpen, onClose } = useDocsDrawerContext() + + return ( + + + {/* TODO: Set the correct background color */} + + + {/* TODO: Add a documentation */} + Documentation + + + + ) +} diff --git a/dapp/src/components/Sidebar/index.tsx b/dapp/src/components/Sidebar/index.tsx new file mode 100644 index 000000000..b07c592c1 --- /dev/null +++ b/dapp/src/components/Sidebar/index.tsx @@ -0,0 +1,31 @@ +import React from "react" +import { Box, Button, useColorModeValue } from "@chakra-ui/react" +import { useDocsDrawerContext, useStakingFlowContext } from "../../hooks" +import DocsDrawer from "../DocsDrawer" + +export default function Sidebar({ marginTop }: { marginTop?: number }) { + const { modalType } = useStakingFlowContext() + const { onOpen } = useDocsDrawerContext() + + return ( + <> + + {/* TODO: Add a correct content for the sidebar */} + + + + + ) +} diff --git a/dapp/src/components/Staking/index.tsx b/dapp/src/components/Staking/index.tsx index b4e56103b..25e3cac04 100644 --- a/dapp/src/components/Staking/index.tsx +++ b/dapp/src/components/Staking/index.tsx @@ -4,6 +4,7 @@ import StakingOverviewModal from "../Modals/StakingOverviewModal" import { useStakingFlowContext, useWalletContext } from "../../hooks" import ModalOverlay from "../ModalOverlay" import { HEADER_HEIGHT } from "../Header" +import Sidebar from "../Sidebar" function Modal() { const { modalType } = useStakingFlowContext() @@ -23,6 +24,7 @@ export default function Staking() { {/* The user has several modals in a flow. Let's use our own modal overlay to prevent the background flickering effect. */} + ) } diff --git a/dapp/src/contexts/DocsDrawerContext.tsx b/dapp/src/contexts/DocsDrawerContext.tsx new file mode 100644 index 000000000..f5097fc96 --- /dev/null +++ b/dapp/src/contexts/DocsDrawerContext.tsx @@ -0,0 +1,44 @@ +import React, { createContext, useCallback, useMemo, useState } from "react" + +type DocsDrawerContextValue = { + isOpen: boolean + onOpen: () => void + onClose: () => void +} + +export const DocsDrawerContext = createContext({ + isOpen: false, + onOpen: () => {}, + onClose: () => {}, +}) + +export function DocsDrawerContextProvider({ + children, +}: { + children: React.ReactNode +}): React.ReactElement { + const [isOpen, setIsOpen] = useState(false) + + const onOpen = useCallback(() => { + setIsOpen(true) + }, []) + + const onClose = useCallback(() => { + setIsOpen(false) + }, []) + + const contextValue: DocsDrawerContextValue = useMemo( + () => ({ + isOpen, + onOpen, + onClose, + }), + [isOpen, onClose, onOpen], + ) + + return ( + + {children} + + ) +} diff --git a/dapp/src/contexts/index.tsx b/dapp/src/contexts/index.tsx index 9271773c0..d05560c99 100644 --- a/dapp/src/contexts/index.tsx +++ b/dapp/src/contexts/index.tsx @@ -1,3 +1,4 @@ export * from "./WalletContext" export * from "./LedgerWalletAPIProvider" export * from "./StakingFlowContext" +export * from "./DocsDrawerContext" diff --git a/dapp/src/hooks/index.ts b/dapp/src/hooks/index.ts index b12025abb..c6fd499d8 100644 --- a/dapp/src/hooks/index.ts +++ b/dapp/src/hooks/index.ts @@ -3,3 +3,4 @@ export * from "./useRequestBitcoinAccount" export * from "./useRequestEthereumAccount" export * from "./useWalletContext" export * from "./useStakingFlowContext" +export * from "./useDocsDrawerContext" diff --git a/dapp/src/hooks/useDocsDrawerContext.ts b/dapp/src/hooks/useDocsDrawerContext.ts new file mode 100644 index 000000000..92b03f2d3 --- /dev/null +++ b/dapp/src/hooks/useDocsDrawerContext.ts @@ -0,0 +1,14 @@ +import { useContext } from "react" +import { DocsDrawerContext } from "../contexts" + +export function useDocsDrawerContext() { + const context = useContext(DocsDrawerContext) + + if (!context) { + throw new Error( + "DocsDrawerContext used outside of DocsDrawerContext component", + ) + } + + return context +} diff --git a/dapp/src/theme/Drawer.ts b/dapp/src/theme/Drawer.ts new file mode 100644 index 000000000..bdb9956e9 --- /dev/null +++ b/dapp/src/theme/Drawer.ts @@ -0,0 +1,11 @@ +import { ComponentSingleStyleConfig } from "@chakra-ui/react" + +const Drawer: ComponentSingleStyleConfig = { + baseStyle: { + dialogContainer: { + zIndex: "drawer", + }, + }, +} + +export default Drawer diff --git a/dapp/src/theme/index.ts b/dapp/src/theme/index.ts index 1445d60d4..822d35145 100644 --- a/dapp/src/theme/index.ts +++ b/dapp/src/theme/index.ts @@ -2,7 +2,8 @@ import { StyleFunctionProps, Tooltip, extendTheme } from "@chakra-ui/react" import { mode } from "@chakra-ui/theme-tools" import Button from "./Button" import Switch from "./Switch" -import { colors } from "./utils" +import { colors, zIndices } from "./utils" +import Drawer from "./Drawer" // Currently, there is no possibility to set all tooltips with hasArrow by defaultProps. // Let's override the defaultProps as follows. @@ -10,6 +11,7 @@ Tooltip.defaultProps = { ...Tooltip.defaultProps, hasArrow: true } const defaultTheme = { colors, + zIndices, styles: { global: (props: StyleFunctionProps) => ({ body: { @@ -21,6 +23,7 @@ const defaultTheme = { components: { Button, Switch, + Drawer, }, } diff --git a/dapp/src/theme/utils/index.ts b/dapp/src/theme/utils/index.ts index c0b5e2654..434c1179b 100644 --- a/dapp/src/theme/utils/index.ts +++ b/dapp/src/theme/utils/index.ts @@ -1 +1,2 @@ export * from "./colors" +export * from "./zIndices" diff --git a/dapp/src/theme/utils/zIndices.ts b/dapp/src/theme/utils/zIndices.ts new file mode 100644 index 000000000..b141510db --- /dev/null +++ b/dapp/src/theme/utils/zIndices.ts @@ -0,0 +1,17 @@ +export const zIndices = { + hide: -1, + auto: "auto", + base: 0, + docked: 10, + dropdown: 1000, + sticky: 1100, + banner: 1200, + overlay: 1300, + modal: 1400, + sidebar: 1450, + drawer: 1470, + popover: 1500, + skipLink: 1600, + toast: 1700, + tooltip: 1800, +} From 72c8e3c429ddb9d538c5cc0a96489e750c1dc8c2 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 6 Dec 2023 12:11:59 +0100 Subject: [PATCH 4/9] Create a custom component for token balance --- dapp/src/components/Header/ConnectWallet.tsx | 13 +++---- .../components/Overview/PositionDetails.tsx | 37 +++++------------- dapp/src/components/TokenBalance/index.tsx | 39 +++++++++++++++++++ dapp/src/utils/numbers.ts | 4 ++ 4 files changed, 59 insertions(+), 34 deletions(-) create mode 100644 dapp/src/components/TokenBalance/index.tsx diff --git a/dapp/src/components/Header/ConnectWallet.tsx b/dapp/src/components/Header/ConnectWallet.tsx index a5c3ef3bb..e47354e9b 100644 --- a/dapp/src/components/Header/ConnectWallet.tsx +++ b/dapp/src/components/Header/ConnectWallet.tsx @@ -15,7 +15,8 @@ import { useRequestEthereumAccount, useWalletContext, } from "../../hooks" -import { formatSatoshiAmount, truncateAddress } from "../../utils" +import { truncateAddress } from "../../utils" +import { TokenBalance } from "../TokenBalance" export type ConnectButtonsProps = { leftIcon: typeof Icon @@ -62,12 +63,10 @@ export default function ConnectWallet() { Balance - - {!btcAccount || btcAccount?.balance.isZero() - ? "0.00" - : formatSatoshiAmount(btcAccount.balance.toString())} - - {BITCOIN.symbol} + Your positions - - - 34.75 - {BITCOIN.symbol} - - - - 1.245.148,1 - {USD.symbol} - - {/* TODO: Add correct text for tooltip */} - - - - - + {/* TODO: Use the real data */} + {/* TODO: Handle click actions */} diff --git a/dapp/src/components/TokenBalance/index.tsx b/dapp/src/components/TokenBalance/index.tsx new file mode 100644 index 000000000..e26818c3e --- /dev/null +++ b/dapp/src/components/TokenBalance/index.tsx @@ -0,0 +1,39 @@ +import React from "react" +import { HStack, Text, Flex } from "@chakra-ui/react" +import { Currency } from "../../types" +import { formatTokenAmount } from "../../utils" +import { USD } from "../../constants" + +type TokenBalanceProps = { + currency: Currency + tokenBalance: string | number + usdBalance?: string + desiredDecimals?: number + alignItems?: "end" | "start" +} + +export function TokenBalance({ + currency, + tokenBalance, + usdBalance, + desiredDecimals = 2, + alignItems = "end", +}: TokenBalanceProps) { + return ( + + + + {formatTokenAmount(tokenBalance, currency.decimals, desiredDecimals)} + + {currency.symbol} + + {usdBalance && ( + // TODO: Set the correct color + + {usdBalance} + {USD.symbol} + + )} + + ) +} diff --git a/dapp/src/utils/numbers.ts b/dapp/src/utils/numbers.ts index dcd077dfd..5e44e49db 100644 --- a/dapp/src/utils/numbers.ts +++ b/dapp/src/utils/numbers.ts @@ -15,6 +15,10 @@ export function bigIntToUserAmount( fixedPointDecimals: number, desiredDecimals = 2, ): string { + if (fixedPoint === BigInt(0)) { + return `0.${"0".repeat(desiredDecimals)}` + } + const fixedPointDesiredDecimalsAmount = fixedPoint / 10n ** BigInt(Math.max(1, fixedPointDecimals - desiredDecimals)) From f6b22b01cc192b655cfbabd2861f67e0d20785ff Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 6 Dec 2023 12:16:44 +0100 Subject: [PATCH 5/9] Init a `StakeModal` component --- dapp/src/components/Modals/StakeModal.tsx | 93 +++++++++++++++++++ .../Modals/StakingOverviewModal.tsx | 4 +- dapp/src/components/Staking/index.tsx | 3 + 3 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 dapp/src/components/Modals/StakeModal.tsx diff --git a/dapp/src/components/Modals/StakeModal.tsx b/dapp/src/components/Modals/StakeModal.tsx new file mode 100644 index 000000000..ba9365d29 --- /dev/null +++ b/dapp/src/components/Modals/StakeModal.tsx @@ -0,0 +1,93 @@ +import React from "react" +import { + Button, + ModalBody, + ModalFooter, + Text, + Flex, + Tabs, + TabList, + Tab, + TabPanels, + TabPanel, + NumberInput, + NumberInputField, + NumberInputStepper, +} from "@chakra-ui/react" +import { useStakingFlowContext } from "../../hooks" +import BaseModal from "./BaseModal" +import { TokenBalance } from "../TokenBalance" +import { BITCOIN } from "../../constants" + +function StakeDetails({ + text, + tokenBalance, + usdBalance, +}: { + text: string + tokenBalance: string + usdBalance: string +}) { + return ( + + {text} + + + ) +} + +export default function StakeModal() { + const { closeModal } = useStakingFlowContext() + + return ( + + + + + Stake + {/* TODO: Add a content for unstake tab */} + Unstake + + + + + {/* TODO: Create a custom number input component */} + + + + + + {/* TODO: Use the real data */} + + + + + + + + + + + + + + ) +} diff --git a/dapp/src/components/Modals/StakingOverviewModal.tsx b/dapp/src/components/Modals/StakingOverviewModal.tsx index e7cbcddb2..44ddc9d33 100644 --- a/dapp/src/components/Modals/StakingOverviewModal.tsx +++ b/dapp/src/components/Modals/StakingOverviewModal.tsx @@ -30,7 +30,7 @@ const STEPS = [ ] export default function StakingOverviewModal() { - const { closeModal } = useStakingFlowContext() + const { setModalType } = useStakingFlowContext() return ( @@ -58,7 +58,7 @@ export default function StakingOverviewModal() { - diff --git a/dapp/src/components/Staking/index.tsx b/dapp/src/components/Staking/index.tsx index 25e3cac04..ba6ed6356 100644 --- a/dapp/src/components/Staking/index.tsx +++ b/dapp/src/components/Staking/index.tsx @@ -5,6 +5,7 @@ import { useStakingFlowContext, useWalletContext } from "../../hooks" import ModalOverlay from "../ModalOverlay" import { HEADER_HEIGHT } from "../Header" import Sidebar from "../Sidebar" +import StakeModal from "../Modals/StakeModal" function Modal() { const { modalType } = useStakingFlowContext() @@ -15,6 +16,8 @@ function Modal() { if (!btcAccount) return if (modalType === "overview") return + + if (modalType === "stake") return } export default function Staking() { From a25c0edef3b551326fde3a00fcda9556bc1805d9 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 6 Dec 2023 12:16:49 +0100 Subject: [PATCH 6/9] Add a custom styles for `Stepper` and `Tabs` --- dapp/src/theme/Stepper.ts | 33 +++++++++++++++++++++++++++++++++ dapp/src/theme/Tabs.ts | 30 ++++++++++++++++++++++++++++++ dapp/src/theme/index.ts | 4 ++++ 3 files changed, 67 insertions(+) create mode 100644 dapp/src/theme/Stepper.ts create mode 100644 dapp/src/theme/Tabs.ts diff --git a/dapp/src/theme/Stepper.ts b/dapp/src/theme/Stepper.ts new file mode 100644 index 000000000..79f438195 --- /dev/null +++ b/dapp/src/theme/Stepper.ts @@ -0,0 +1,33 @@ +import { mode } from "@chakra-ui/theme-tools" +import type { StyleFunctionProps } from "@chakra-ui/styled-system" +import { ComponentSingleStyleConfig } from "@chakra-ui/react" + +const Stepper: ComponentSingleStyleConfig = { + baseStyle: { + indicator: { + borderRadius: 4, + fontWeight: "500", + }, + step: { + gap: 6, + }, + }, + variants: { + basic: (props: StyleFunctionProps) => ({ + indicator: { + "&[data-status=complete]": { + // TODO: Set the correct color + background: mode("black", "purple")(props), + }, + }, + separator: { + "&[data-status=complete]": { + // TODO: Set the correct color + background: mode("black", "purple")(props), + }, + }, + }), + }, +} + +export default Stepper diff --git a/dapp/src/theme/Tabs.ts b/dapp/src/theme/Tabs.ts new file mode 100644 index 000000000..f864f610b --- /dev/null +++ b/dapp/src/theme/Tabs.ts @@ -0,0 +1,30 @@ +import { mode } from "@chakra-ui/theme-tools" +import type { StyleFunctionProps } from "@chakra-ui/styled-system" +import { ComponentSingleStyleConfig } from "@chakra-ui/react" + +const Tabs: ComponentSingleStyleConfig = { + variants: { + underline: (props: StyleFunctionProps) => ({ + tab: { + padding: 0, + fontWeight: 700, + borderBottom: "4px solid", + borderColor: "transparent", + background: "transparent", + _selected: { + // TODO: Set the correct color + color: mode("black", "black")(props), + borderColor: mode("#F34900", "#F34900")(props), + }, + // TODO: Set the correct color + color: mode("#675E60", "#675E60")(props), + }, + tablist: { + borderBottom: "none", + gap: 8, + }, + }), + }, +} + +export default Tabs diff --git a/dapp/src/theme/index.ts b/dapp/src/theme/index.ts index 822d35145..dbdbf4f1b 100644 --- a/dapp/src/theme/index.ts +++ b/dapp/src/theme/index.ts @@ -4,6 +4,8 @@ import Button from "./Button" import Switch from "./Switch" import { colors, zIndices } from "./utils" import Drawer from "./Drawer" +import Stepper from "./Stepper" +import Tabs from "./Tabs" // Currently, there is no possibility to set all tooltips with hasArrow by defaultProps. // Let's override the defaultProps as follows. @@ -24,6 +26,8 @@ const defaultTheme = { Button, Switch, Drawer, + Stepper, + Tabs, }, } From 70073dbf812acd27cb1d75b46ee400d85f75ffec Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 6 Dec 2023 14:35:33 +0100 Subject: [PATCH 7/9] Start using a shared typography --- dapp/src/components/Header/ConnectWallet.tsx | 4 ++-- dapp/src/components/Modals/ConnectWalletModal.tsx | 8 ++++---- dapp/src/components/Modals/StakeModal.tsx | 4 ++-- dapp/src/components/Overview/PositionDetails.tsx | 5 +++-- dapp/src/components/TokenBalance/index.tsx | 13 +++++++------ 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/dapp/src/components/Header/ConnectWallet.tsx b/dapp/src/components/Header/ConnectWallet.tsx index e47354e9b..cea1d2589 100644 --- a/dapp/src/components/Header/ConnectWallet.tsx +++ b/dapp/src/components/Header/ConnectWallet.tsx @@ -3,7 +3,6 @@ import { Button, HStack, Icon, - Text, Tooltip, useColorModeValue, } from "@chakra-ui/react" @@ -17,6 +16,7 @@ import { } from "../../hooks" import { truncateAddress } from "../../utils" import { TokenBalance } from "../TokenBalance" +import { TextMd } from "../Typography" export type ConnectButtonsProps = { leftIcon: typeof Icon @@ -62,7 +62,7 @@ export default function ConnectWallet() { return ( - Balance + Balance - Bitcoin account not installed + Bitcoin account not installed - + Bitcoin account is required to make transactions for depositing and staking your BTC. - + diff --git a/dapp/src/components/Modals/StakeModal.tsx b/dapp/src/components/Modals/StakeModal.tsx index ba9365d29..581431e08 100644 --- a/dapp/src/components/Modals/StakeModal.tsx +++ b/dapp/src/components/Modals/StakeModal.tsx @@ -3,7 +3,6 @@ import { Button, ModalBody, ModalFooter, - Text, Flex, Tabs, TabList, @@ -18,6 +17,7 @@ import { useStakingFlowContext } from "../../hooks" import BaseModal from "./BaseModal" import { TokenBalance } from "../TokenBalance" import { BITCOIN } from "../../constants" +import { TextMd } from "../Typography" function StakeDetails({ text, @@ -30,7 +30,7 @@ function StakeDetails({ }) { return ( - {text} + {text} - Your positions + Your positions {/* TODO: Use the real data */} - + {formatTokenAmount(tokenBalance, currency.decimals, desiredDecimals)} - - {currency.symbol} + + {currency.symbol} {usdBalance && ( // TODO: Set the correct color - {usdBalance} - {USD.symbol} + {usdBalance} + {USD.symbol} )} From 3ac1c6c8a026b6350751170b86b21fcc8df4644b Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 6 Dec 2023 15:03:50 +0100 Subject: [PATCH 8/9] Small code fixes --- dapp/src/components/ModalOverlay/index.tsx | 1 - dapp/src/components/Modals/ConnectWalletModal.tsx | 4 ++-- dapp/src/components/Modals/StakingOverviewModal.tsx | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/dapp/src/components/ModalOverlay/index.tsx b/dapp/src/components/ModalOverlay/index.tsx index 9ca30d1f1..b4f18e542 100644 --- a/dapp/src/components/ModalOverlay/index.tsx +++ b/dapp/src/components/ModalOverlay/index.tsx @@ -33,7 +33,6 @@ export default function ModalOverlay({ marginTop }: { marginTop?: number }) { zIndex="overlay" // Hide the element when it is no longer needed. display={showOverlay ? "block" : "none"} - // zIndex={showOverlay ? "overlay" : "-1"} transition={`opacity ${DELAY}ms`} mt={marginTop} /> diff --git a/dapp/src/components/Modals/ConnectWalletModal.tsx b/dapp/src/components/Modals/ConnectWalletModal.tsx index 908899586..2658ac432 100644 --- a/dapp/src/components/Modals/ConnectWalletModal.tsx +++ b/dapp/src/components/Modals/ConnectWalletModal.tsx @@ -20,8 +20,8 @@ export default function ConnectWalletModal() { Bitcoin account not installed - - + + Bitcoin account is required to make transactions for depositing and diff --git a/dapp/src/components/Modals/StakingOverviewModal.tsx b/dapp/src/components/Modals/StakingOverviewModal.tsx index 44ddc9d33..d54999747 100644 --- a/dapp/src/components/Modals/StakingOverviewModal.tsx +++ b/dapp/src/components/Modals/StakingOverviewModal.tsx @@ -37,9 +37,9 @@ export default function StakingOverviewModal() { Staking overview From 446359435db3354ec6a90453353312e43be8d6ee Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Thu, 7 Dec 2023 13:22:52 +0100 Subject: [PATCH 9/9] Make sure all needed accounts are connected After clicking on the stake button, if the user has no accounts connected, should see special modals with connection options. --- .../components/Modals/ConnectWalletModal.tsx | 30 +++++++++++------- dapp/src/components/Staking/index.tsx | 27 ++++++++++++++-- dapp/src/static/images/ConnectETHAccount.png | Bin 0 -> 5301 bytes dapp/src/types/ledger-live-app.ts | 2 +- 4 files changed, 44 insertions(+), 15 deletions(-) create mode 100644 dapp/src/static/images/ConnectETHAccount.png diff --git a/dapp/src/components/Modals/ConnectWalletModal.tsx b/dapp/src/components/Modals/ConnectWalletModal.tsx index 2658ac432..b36faf402 100644 --- a/dapp/src/components/Modals/ConnectWalletModal.tsx +++ b/dapp/src/components/Modals/ConnectWalletModal.tsx @@ -6,26 +6,34 @@ import { ModalFooter, ModalHeader, VStack, + Text, } from "@chakra-ui/react" -import { useRequestBitcoinAccount } from "../../hooks" import BaseModal from "./BaseModal" -import ConnectBTCAccount from "../../static/images/ConnectBTCAccount.png" -import { TextLg, TextMd } from "../Typography" +import { Currency, RequestAccountParams } from "../../types" +import { TextMd } from "../Typography" -export default function ConnectWalletModal() { - const { requestAccount } = useRequestBitcoinAccount() +type ConnectWalletModalProps = { + currency: Currency + image: string + requestAccount: (...params: RequestAccountParams) => Promise +} +export default function ConnectWalletModal({ + currency, + image, + requestAccount, +}: ConnectWalletModalProps) { return ( - Bitcoin account not installed + {currency.name} account not installed - - - + + + - Bitcoin account is required to make transactions for depositing and - staking your BTC. + {currency.name} account is required to make transactions for + depositing and staking your {currency.symbol}. diff --git a/dapp/src/components/Staking/index.tsx b/dapp/src/components/Staking/index.tsx index ba6ed6356..b3e42621b 100644 --- a/dapp/src/components/Staking/index.tsx +++ b/dapp/src/components/Staking/index.tsx @@ -1,19 +1,40 @@ import React from "react" import ConnectWalletModal from "../Modals/ConnectWalletModal" import StakingOverviewModal from "../Modals/StakingOverviewModal" -import { useStakingFlowContext, useWalletContext } from "../../hooks" +import { useRequestBitcoinAccount, useRequestEthereumAccount, useStakingFlowContext, useWalletContext } from "../../hooks" import ModalOverlay from "../ModalOverlay" import { HEADER_HEIGHT } from "../Header" import Sidebar from "../Sidebar" import StakeModal from "../Modals/StakeModal" +import { BITCOIN, ETHEREUM } from "../../constants" +import ConnectBTCAccount from "../../static/images/ConnectBTCAccount.png" +import ConnectETHAccount from "../../static/images/ConnectETHAccount.png" function Modal() { const { modalType } = useStakingFlowContext() - const { btcAccount } = useWalletContext() + const { btcAccount, ethAccount } = useWalletContext() + const { requestAccount: requestBitcoinAccount } = useRequestBitcoinAccount() + const { requestAccount: requestEthereumAccount } = useRequestEthereumAccount() if (!modalType) return null - if (!btcAccount) return + if (!btcAccount) + return ( + + ) + + if (!ethAccount) + return ( + + ) if (modalType === "overview") return diff --git a/dapp/src/static/images/ConnectETHAccount.png b/dapp/src/static/images/ConnectETHAccount.png new file mode 100644 index 0000000000000000000000000000000000000000..e1ad2974ddd2f2a15094405189d8391ffb76ffe6 GIT binary patch literal 5301 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 Hu0mjf@k38l literal 0 HcmV?d00001 diff --git a/dapp/src/types/ledger-live-app.ts b/dapp/src/types/ledger-live-app.ts index c63368d3e..1fa680d07 100644 --- a/dapp/src/types/ledger-live-app.ts +++ b/dapp/src/types/ledger-live-app.ts @@ -1,6 +1,6 @@ import { WalletAPIClient } from "@ledgerhq/wallet-api-client" -type RequestAccountParams = Parameters +export type RequestAccountParams = Parameters export type UseRequestAccountReturn = { requestAccount: (...params: RequestAccountParams) => Promise