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/DApp.tsx b/dapp/src/DApp.tsx index 085b6fbe8..d87e33642 100644 --- a/dapp/src/DApp.tsx +++ b/dapp/src/DApp.tsx @@ -2,7 +2,12 @@ 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, + DocsDrawerContextProvider, +} from "./contexts" import Header from "./components/Header" import Overview from "./components/Overview" @@ -23,9 +28,13 @@ function DAppProviders() { return ( - - - + + + + + + + ) 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/Header/ConnectWallet.tsx b/dapp/src/components/Header/ConnectWallet.tsx index 8b35a010b..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" @@ -15,12 +14,14 @@ import { useRequestEthereumAccount, useWalletContext, } from "../../hooks" -import { formatSatoshiAmount, truncateAddress } from "../../utils" +import { truncateAddress } from "../../utils" +import { TokenBalance } from "../TokenBalance" +import { TextMd } from "../Typography" export type ConnectButtonsProps = { leftIcon: typeof Icon rightIcon: typeof Icon - account: Account | undefined + account?: Account requestAccount: () => Promise } @@ -61,13 +62,11 @@ export default function ConnectWallet() { return ( - Balance - - {!btcAccount || btcAccount?.balance.isZero() - ? "0.00" - : formatSatoshiAmount(btcAccount.balance.toString())} - - {BITCOIN.symbol} + Balance + + ) diff --git a/dapp/src/components/ModalOverlay/index.tsx b/dapp/src/components/ModalOverlay/index.tsx new file mode 100644 index 000000000..b4f18e542 --- /dev/null +++ b/dapp/src/components/ModalOverlay/index.tsx @@ -0,0 +1,40 @@ +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..b36faf402 --- /dev/null +++ b/dapp/src/components/Modals/ConnectWalletModal.tsx @@ -0,0 +1,52 @@ +import React from "react" +import { + Button, + Image, + ModalBody, + ModalFooter, + ModalHeader, + VStack, + Text, +} from "@chakra-ui/react" +import BaseModal from "./BaseModal" +import { Currency, RequestAccountParams } from "../../types" +import { TextMd } from "../Typography" + +type ConnectWalletModalProps = { + currency: Currency + image: string + requestAccount: (...params: RequestAccountParams) => Promise +} + +export default function ConnectWalletModal({ + currency, + image, + requestAccount, +}: ConnectWalletModalProps) { + return ( + + + {currency.name} account not installed + + + + + + {currency.name} account is required to make transactions for + depositing and staking your {currency.symbol}. + + + + + + + + ) +} diff --git a/dapp/src/components/Modals/StakeModal.tsx b/dapp/src/components/Modals/StakeModal.tsx new file mode 100644 index 000000000..581431e08 --- /dev/null +++ b/dapp/src/components/Modals/StakeModal.tsx @@ -0,0 +1,93 @@ +import React from "react" +import { + Button, + ModalBody, + ModalFooter, + 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" +import { TextMd } from "../Typography" + +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 new file mode 100644 index 000000000..d54999747 --- /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 { setModalType } = 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..4606692dd 100644 --- a/dapp/src/components/Overview/PositionDetails.tsx +++ b/dapp/src/components/Overview/PositionDetails.tsx @@ -1,43 +1,34 @@ import React from "react" -import { - Text, - Button, - HStack, - Tooltip, - Icon, - useColorModeValue, - Flex, -} from "@chakra-ui/react" -import { BITCOIN, USD } from "../../constants" -import { Info } from "../../static/icons" +import { Button, Flex } from "@chakra-ui/react" +import { BITCOIN } from "../../constants" +import Staking from "../Staking" +import { useStakingFlowContext } from "../../hooks" +import { TokenBalance } from "../TokenBalance" +import { TextMd } from "../Typography" export default function PositionDetails() { + const { setModalType } = useStakingFlowContext() + return ( - - - Your positions - - - 34.75 - {BITCOIN.symbol} - - - - 1.245.148,1 - {USD.symbol} - - {/* TODO: Add correct text for tooltip */} - - - - + <> + + + Your positions + {/* TODO: Use the real data */} + + + + {/* TODO: Handle click actions */} + + - - {/* TODO: Handle click actions */} - - - - + + ) } 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 new file mode 100644 index 000000000..b3e42621b --- /dev/null +++ b/dapp/src/components/Staking/index.tsx @@ -0,0 +1,54 @@ +import React from "react" +import ConnectWalletModal from "../Modals/ConnectWalletModal" +import StakingOverviewModal from "../Modals/StakingOverviewModal" +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, ethAccount } = useWalletContext() + const { requestAccount: requestBitcoinAccount } = useRequestBitcoinAccount() + const { requestAccount: requestEthereumAccount } = useRequestEthereumAccount() + + if (!modalType) return null + + if (!btcAccount) + return ( + + ) + + if (!ethAccount) + return ( + + ) + + if (modalType === "overview") return + + if (modalType === "stake") 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/components/TokenBalance/index.tsx b/dapp/src/components/TokenBalance/index.tsx new file mode 100644 index 000000000..7d8fcc13e --- /dev/null +++ b/dapp/src/components/TokenBalance/index.tsx @@ -0,0 +1,40 @@ +import React from "react" +import { HStack, Flex } from "@chakra-ui/react" +import { Currency } from "../../types" +import { formatTokenAmount } from "../../utils" +import { USD } from "../../constants" +import { TextMd, TextSm } from "../Typography" + +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/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/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..d05560c99 100644 --- a/dapp/src/contexts/index.tsx +++ b/dapp/src/contexts/index.tsx @@ -1,2 +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 038388476..c6fd499d8 100644 --- a/dapp/src/hooks/index.ts +++ b/dapp/src/hooks/index.ts @@ -2,3 +2,5 @@ export * from "./useDetectThemeMode" 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/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 000000000..deff3c0cc Binary files /dev/null and b/dapp/src/static/images/ConnectBTCAccount.png differ diff --git a/dapp/src/static/images/ConnectETHAccount.png b/dapp/src/static/images/ConnectETHAccount.png new file mode 100644 index 000000000..e1ad2974d Binary files /dev/null and b/dapp/src/static/images/ConnectETHAccount.png differ 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/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 de73c60c8..41f5418b0 100644 --- a/dapp/src/theme/index.ts +++ b/dapp/src/theme/index.ts @@ -2,7 +2,10 @@ 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, fontSizes, fontWeights, lineHeights } from "./utils" +import Drawer from "./Drawer" +import Stepper from "./Stepper" +import Tabs from "./Tabs" +import { colors, fontSizes, fontWeights, lineHeights, zIndices } from "./utils" // Currently, there is no possibility to set all tooltips with hasArrow by defaultProps. // Let's override the defaultProps as follows. @@ -13,6 +16,7 @@ const defaultTheme = { fontSizes, fontWeights, lineHeights, + zIndices, styles: { global: (props: StyleFunctionProps) => ({ body: { @@ -24,6 +28,9 @@ const defaultTheme = { components: { Button, Switch, + Drawer, + Stepper, + Tabs, }, } diff --git a/dapp/src/theme/utils/index.ts b/dapp/src/theme/utils/index.ts index 9f377b3e3..a125c015d 100644 --- a/dapp/src/theme/utils/index.ts +++ b/dapp/src/theme/utils/index.ts @@ -1,2 +1,3 @@ export * from "./colors" +export * from "./zIndices" export * from "./fonts" 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, +} 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/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 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" 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))