diff --git a/dapp/src/components/Layout.tsx b/dapp/src/components/Layout.tsx
index 08c738b2b..43a0bc2d3 100644
--- a/dapp/src/components/Layout.tsx
+++ b/dapp/src/components/Layout.tsx
@@ -1,10 +1,10 @@
-import React from "react"
+import React, { useState } from "react"
import { AnimatePresence, motion, Variants } from "framer-motion"
-import { useState } from "react"
import { useLocation, useOutlet } from "react-router-dom"
import DocsDrawer from "./DocsDrawer"
import Header from "./Header"
import Sidebar from "./Sidebar"
+import ModalRoot from "./ModalRoot"
const wrapperVariants: Variants = {
in: { opacity: 0, y: 48 },
@@ -39,6 +39,7 @@ function Layout() {
+
>
)
}
diff --git a/dapp/src/components/ModalRoot/index.tsx b/dapp/src/components/ModalRoot/index.tsx
new file mode 100644
index 000000000..22e6187f5
--- /dev/null
+++ b/dapp/src/components/ModalRoot/index.tsx
@@ -0,0 +1,19 @@
+import React, { ElementType } from "react"
+import { useModal } from "#/hooks"
+import { ModalType } from "#/types"
+import TransactionModal from "../TransactionModal"
+
+const MODALS: Record = {
+ STAKE: TransactionModal,
+ UNSTAKE: TransactionModal,
+} as const
+
+export default function ModalRoot() {
+ const { modalType, modalProps, closeModal } = useModal()
+
+ if (!modalType) {
+ return null
+ }
+ const SpecificModal = MODALS[modalType]
+ return
+}
diff --git a/dapp/src/components/ModalRoot/withBaseModal.tsx b/dapp/src/components/ModalRoot/withBaseModal.tsx
new file mode 100644
index 000000000..de804ca0d
--- /dev/null
+++ b/dapp/src/components/ModalRoot/withBaseModal.tsx
@@ -0,0 +1,29 @@
+import React, { ComponentType } from "react"
+import { Modal, ModalContent, ModalOverlay } from "@chakra-ui/react"
+import { BaseModalProps } from "#/types"
+
+export const MODAL_BASE_SIZE = "lg"
+
+function withBaseModal(
+ WrappedModalContent: ComponentType,
+) {
+ return function ModalBase(props: T) {
+ const { closeModal } = props
+ return (
+
+
+
+
+
+
+ )
+ }
+}
+
+export default withBaseModal
diff --git a/dapp/src/components/TransactionModal/ActionFormModal.tsx b/dapp/src/components/TransactionModal/ActionFormModal.tsx
index cc0ac9b67..3c1cbed37 100644
--- a/dapp/src/components/TransactionModal/ActionFormModal.tsx
+++ b/dapp/src/components/TransactionModal/ActionFormModal.tsx
@@ -1,13 +1,10 @@
import React, { ReactNode, useCallback, useState } from "react"
import { Box, ModalBody, ModalCloseButton, ModalHeader } from "@chakra-ui/react"
-import {
- useStakeFlowContext,
- useTransactionContext,
- useWalletContext,
-} from "#/hooks"
+import { useAppDispatch, useStakeFlowContext, useWalletContext } from "#/hooks"
import { ACTION_FLOW_TYPES, ActionFlowType, BaseFormProps } from "#/types"
import { TokenAmountFormValues } from "#/components/shared/TokenAmountForm/TokenAmountFormBase"
import { logPromiseFailure } from "#/utils"
+import { setTokenAmount } from "#/store/action-flow"
import StakeFormModal from "./ActiveStakingStep/StakeFormModal"
import UnstakeFormModal from "./ActiveUnstakingStep/UnstakeFormModal"
@@ -30,8 +27,8 @@ const FORM_DATA: Record<
function ActionFormModal({ type }: { type: ActionFlowType }) {
const { btcAccount, ethAccount } = useWalletContext()
- const { setTokenAmount } = useTransactionContext()
const { initStake } = useStakeFlowContext()
+ const dispatch = useAppDispatch()
const [isLoading, setIsLoading] = useState(false)
@@ -55,14 +52,14 @@ function ActionFormModal({ type }: { type: ActionFlowType }) {
// TODO: Init unstake flow
if (type === ACTION_FLOW_TYPES.STAKE) await handleInitStake()
- setTokenAmount({ amount: values.amount, currency: "bitcoin" })
+ dispatch(setTokenAmount({ amount: values.amount, currency: "bitcoin" }))
} catch (error) {
console.error(error)
} finally {
setIsLoading(false)
}
},
- [handleInitStake, setTokenAmount, type],
+ [dispatch, handleInitStake, type],
)
const handleSubmitFormWrapper = useCallback(
diff --git a/dapp/src/components/TransactionModal/ActiveFlowStep.tsx b/dapp/src/components/TransactionModal/ActiveFlowStep.tsx
index 0e27f2f74..bf8e5eafa 100644
--- a/dapp/src/components/TransactionModal/ActiveFlowStep.tsx
+++ b/dapp/src/components/TransactionModal/ActiveFlowStep.tsx
@@ -1,5 +1,5 @@
import React, { ReactElement, useEffect } from "react"
-import { useModalFlowContext } from "#/hooks"
+import { useActionFlowActiveStep, useActionFlowType, useModal } from "#/hooks"
import {
ACTION_FLOW_STEPS_TYPES,
ActionFlowType,
@@ -18,14 +18,17 @@ const FLOW: Record ReactElement> = {
}
export function ActiveFlowStep() {
- const { activeStep, type, onClose } = useModalFlowContext()
+ const { closeModal } = useModal()
+ const activeStep = useActionFlowActiveStep()
+ const type = useActionFlowType()
+
const numberOfSteps = Object.keys(ACTION_FLOW_STEPS_TYPES[type]).length
useEffect(() => {
if (activeStep > numberOfSteps) {
- onClose()
+ closeModal()
}
- }, [activeStep, numberOfSteps, onClose])
+ }, [activeStep, closeModal, numberOfSteps])
return FLOW[type](activeStep)
}
diff --git a/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx b/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx
index 1878b03c3..f3fb591e5 100644
--- a/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx
+++ b/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx
@@ -1,12 +1,12 @@
import React, { useCallback } from "react"
import {
+ useActionFlowTokenAmount,
+ useAppDispatch,
useDepositBTCTransaction,
useDepositTelemetry,
useExecuteFunction,
- useModalFlowContext,
useStakeFlowContext,
useToast,
- useTransactionContext,
useWalletContext,
} from "#/hooks"
import { logPromiseFailure } from "#/utils"
@@ -17,27 +17,28 @@ import Spinner from "#/components/shared/Spinner"
import { TextMd } from "#/components/shared/Typography"
import { CardAlert } from "#/components/shared/alerts"
import { ONE_SEC_IN_MILLISECONDS } from "#/constants"
+import { setStatus } from "#/store/action-flow"
-const DELAY = ONE_SEC_IN_MILLISECONDS * 2
+const DELAY = ONE_SEC_IN_MILLISECONDS
const TOAST_ID = TOAST_IDS.DEPOSIT_TRANSACTION_ERROR
const TOAST = TOASTS[TOAST_ID]
export default function DepositBTCModal() {
const { ethAccount } = useWalletContext()
- const { tokenAmount } = useTransactionContext()
- const { setStatus } = useModalFlowContext()
+ const tokenAmount = useActionFlowTokenAmount()
const { btcAddress, depositReceipt, stake } = useStakeFlowContext()
const depositTelemetry = useDepositTelemetry()
const { closeToast, openToast } = useToast()
+ const dispatch = useAppDispatch()
const onStakeBTCSuccess = useCallback(
- () => setStatus(PROCESS_STATUSES.SUCCEEDED),
- [setStatus],
+ () => dispatch(setStatus(PROCESS_STATUSES.SUCCEEDED)),
+ [dispatch],
)
const onStakeBTCError = useCallback(() => {
- setStatus(PROCESS_STATUSES.FAILED)
- }, [setStatus])
+ dispatch(setStatus(PROCESS_STATUSES.FAILED))
+ }, [dispatch])
const handleStake = useExecuteFunction(
stake,
@@ -47,10 +48,10 @@ export default function DepositBTCModal() {
const onDepositBTCSuccess = useCallback(() => {
closeToast(TOAST_ID)
- setStatus(PROCESS_STATUSES.LOADING)
+ dispatch(setStatus(PROCESS_STATUSES.LOADING))
logPromiseFailure(handleStake())
- }, [closeToast, setStatus, handleStake])
+ }, [closeToast, dispatch, handleStake])
const showError = useCallback(() => {
openToast({
diff --git a/dapp/src/components/TransactionModal/ActiveStakingStep/StakingErrorModal/ServerErrorModal.tsx b/dapp/src/components/TransactionModal/ActiveStakingStep/StakingErrorModal/ServerErrorModal.tsx
index 179c0d62c..e83409338 100644
--- a/dapp/src/components/TransactionModal/ActiveStakingStep/StakingErrorModal/ServerErrorModal.tsx
+++ b/dapp/src/components/TransactionModal/ActiveStakingStep/StakingErrorModal/ServerErrorModal.tsx
@@ -15,7 +15,7 @@ import { CableWithPlugIcon, Info } from "#/assets/icons"
import { TextMd } from "#/components/shared/Typography"
import { EXTERNAL_HREF } from "#/constants"
import IconWrapper from "#/components/shared/IconWrapper"
-import { MODAL_BASE_SIZE } from "#/components/shared/ModalBase"
+import { MODAL_BASE_SIZE } from "#/components/ModalRoot/withBaseModal"
import {
IconBrandDiscordFilled,
IconReload,
diff --git a/dapp/src/components/TransactionModal/ActiveStakingStep/StakingErrorModal/index.tsx b/dapp/src/components/TransactionModal/ActiveStakingStep/StakingErrorModal/index.tsx
index 6ae4e1276..969a4e145 100644
--- a/dapp/src/components/TransactionModal/ActiveStakingStep/StakingErrorModal/index.tsx
+++ b/dapp/src/components/TransactionModal/ActiveStakingStep/StakingErrorModal/index.tsx
@@ -1,25 +1,26 @@
import React, { useCallback, useState } from "react"
import {
+ useAppDispatch,
useExecuteFunction,
- useModalFlowContext,
useStakeFlowContext,
} from "#/hooks"
import { PROCESS_STATUSES } from "#/types"
import { logPromiseFailure } from "#/utils"
+import { setStatus } from "#/store/action-flow"
import ServerErrorModal from "./ServerErrorModal"
import RetryModal from "./RetryModal"
import LoadingModal from "../../LoadingModal"
export default function StakingErrorModal() {
- const { setStatus } = useModalFlowContext()
const { stake } = useStakeFlowContext()
+ const dispatch = useAppDispatch()
const [isLoading, setIsLoading] = useState(false)
const [isServerError, setIsServerError] = useState(false)
const onStakeBTCSuccess = useCallback(
- () => setStatus(PROCESS_STATUSES.SUCCEEDED),
- [setStatus],
+ () => dispatch(setStatus(PROCESS_STATUSES.SUCCEEDED)),
+ [dispatch],
)
const onStakeBTCError = useCallback(() => setIsServerError(true), [])
diff --git a/dapp/src/components/TransactionModal/ActiveUnstakingStep/SignMessageModal.tsx b/dapp/src/components/TransactionModal/ActiveUnstakingStep/SignMessageModal.tsx
index e46359396..3a8950325 100644
--- a/dapp/src/components/TransactionModal/ActiveUnstakingStep/SignMessageModal.tsx
+++ b/dapp/src/components/TransactionModal/ActiveUnstakingStep/SignMessageModal.tsx
@@ -1,21 +1,22 @@
import React, { useCallback } from "react"
-import { useExecuteFunction, useModalFlowContext } from "#/hooks"
+import { useAppDispatch, useExecuteFunction } from "#/hooks"
import { PROCESS_STATUSES } from "#/types"
import { Button, ModalBody, ModalFooter, ModalHeader } from "@chakra-ui/react"
import { TextMd } from "#/components/shared/Typography"
import { logPromiseFailure } from "#/utils"
+import { setStatus } from "#/store/action-flow"
export default function SignMessageModal() {
- const { setStatus } = useModalFlowContext()
+ const dispatch = useAppDispatch()
const onSignMessageSuccess = useCallback(() => {
- setStatus(PROCESS_STATUSES.SUCCEEDED)
- }, [setStatus])
+ dispatch(setStatus(PROCESS_STATUSES.SUCCEEDED))
+ }, [dispatch])
// TODO: After a failed attempt, we should display the message
const onSignMessageError = useCallback(() => {
- setStatus(PROCESS_STATUSES.FAILED)
- }, [setStatus])
+ dispatch(setStatus(PROCESS_STATUSES.FAILED))
+ }, [dispatch])
const handleSignMessage = useExecuteFunction(
// TODO: Use a correct function from the SDK
@@ -25,13 +26,13 @@ export default function SignMessageModal() {
)
const handleSignMessageWrapper = useCallback(() => {
- setStatus(PROCESS_STATUSES.LOADING)
+ dispatch(setStatus(PROCESS_STATUSES.LOADING))
// TODO: Remove when SDK is ready
setTimeout(() => {
logPromiseFailure(handleSignMessage())
}, 5000)
- }, [setStatus, handleSignMessage])
+ }, [dispatch, handleSignMessage])
return (
<>
diff --git a/dapp/src/components/TransactionModal/ModalContentWrapper.tsx b/dapp/src/components/TransactionModal/ModalContentWrapper.tsx
index 776b36ec3..cfe99aea7 100644
--- a/dapp/src/components/TransactionModal/ModalContentWrapper.tsx
+++ b/dapp/src/components/TransactionModal/ModalContentWrapper.tsx
@@ -1,9 +1,10 @@
import React from "react"
import {
- useModalFlowContext,
+ useActionFlowStatus,
+ useActionFlowTokenAmount,
+ useActionFlowType,
useRequestBitcoinAccount,
useRequestEthereumAccount,
- useTransactionContext,
useWalletContext,
} from "#/hooks"
import { BitcoinIcon, EthereumIcon } from "#/assets/icons"
@@ -23,8 +24,9 @@ export default function ModalContentWrapper({
const { btcAccount, ethAccount } = useWalletContext()
const { requestAccount: requestBitcoinAccount } = useRequestBitcoinAccount()
const { requestAccount: requestEthereumAccount } = useRequestEthereumAccount()
- const { type, status } = useModalFlowContext()
- const { tokenAmount } = useTransactionContext()
+ const status = useActionFlowStatus()
+ const type = useActionFlowType()
+ const tokenAmount = useActionFlowTokenAmount()
if (!btcAccount || !isSupportedBTCAddressType(btcAccount.address))
return (
diff --git a/dapp/src/components/TransactionModal/SuccessModal.tsx b/dapp/src/components/TransactionModal/SuccessModal.tsx
index 00811bbc5..0a2d84b6d 100644
--- a/dapp/src/components/TransactionModal/SuccessModal.tsx
+++ b/dapp/src/components/TransactionModal/SuccessModal.tsx
@@ -8,7 +8,7 @@ import {
VStack,
} from "@chakra-ui/react"
import { LoadingSpinnerSuccessIcon } from "#/assets/icons"
-import { useModalFlowContext } from "#/hooks"
+import { useModal } from "#/hooks"
import { CurrencyBalanceWithConversion } from "#/components/shared/CurrencyBalanceWithConversion"
import { ACTION_FLOW_TYPES, ActionFlowType, TokenAmount } from "#/types"
import { TextMd } from "../shared/Typography"
@@ -66,7 +66,7 @@ type SuccessModalProps = {
}
export default function SuccessModal({ type, tokenAmount }: SuccessModalProps) {
- const { onClose } = useModalFlowContext()
+ const { closeModal } = useModal()
const { header, footer, renderBody } = CONTENT[type]
@@ -80,7 +80,7 @@ export default function SuccessModal({ type, tokenAmount }: SuccessModalProps) {
-