Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dApp: Handle deposit rejection #453

Merged
merged 6 commits into from
Jun 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import React, { useCallback, useEffect } from "react"
import {
useActionFlowPause,
useActionFlowTokenAmount,
useAppDispatch,
useDepositBTCTransaction,
useExecuteFunction,
useStakeFlowContext,
useVerifyDepositAddress,
} from "#/hooks"
import { logPromiseFailure } from "#/utils"
import { PROCESS_STATUSES } from "#/types"
import { isLedgerLiveError, logPromiseFailure } from "#/utils"
import { PROCESS_STATUSES, LedgerLiveError } from "#/types"
import { Highlight } from "@chakra-ui/react"
import { TextMd } from "#/components/shared/Typography"
import { CardAlert } from "#/components/shared/alerts"
Expand All @@ -20,6 +21,7 @@ export default function DepositBTCModal() {
const { btcAddress, depositReceipt, stake } = useStakeFlowContext()
const verifyDepositAddress = useVerifyDepositAddress()
const dispatch = useAppDispatch()
const { handlePause } = useActionFlowPause()

const onStakeBTCSuccess = useCallback(() => {
dispatch(setStatus(PROCESS_STATUSES.SUCCEEDED))
Expand All @@ -42,9 +44,22 @@ export default function DepositBTCModal() {
}, [dispatch, handleStake])

// TODO: Handle when the function fails
const showError = useCallback(() => {}, [])
const showError = useCallback((error?: LedgerLiveError) => {
console.error(error)
}, [])

const onDepositBTCError = useCallback(() => showError(), [showError])
const onDepositBTCError = useCallback(
(error: unknown) => {
if (!isLedgerLiveError(error)) return

const isInterrupted =
error.message && error.message.includes("Signature interrupted by user")
if (isInterrupted) handlePause()

showError(error)
},
[showError, handlePause],
)

const { sendBitcoinTransaction, transactionHash } = useDepositBTCTransaction(
onDepositBTCSuccess,
Expand Down
3 changes: 3 additions & 0 deletions dapp/src/components/TransactionModal/ModalContentWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import ErrorModal from "./ErrorModal"
import LoadingModal from "./LoadingModal"
import MissingAccountModal from "./MissingAccountModal"
import SuccessModal from "./SuccessModal"
import ResumeModal from "./ResumeModal"

export default function ModalContentWrapper({
children,
Expand Down Expand Up @@ -43,5 +44,7 @@ export default function ModalContentWrapper({

if (status === PROCESS_STATUSES.FAILED) return <ErrorModal type={type} />

if (status === PROCESS_STATUSES.PAUSED) return <ResumeModal />

return children
}
42 changes: 42 additions & 0 deletions dapp/src/components/TransactionModal/ResumeModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from "react"
import {
ModalHeader,
ModalBody,
ModalFooter,
Button,
HStack,
} from "@chakra-ui/react"

import Spinner from "#/components/shared/Spinner"
import { PauseIcon } from "#/assets/icons"
import { TextMd } from "#/components/shared/Typography"
import { useActionFlowPause, useModal } from "#/hooks"

export default function ResumeModal() {
const { handleResume } = useActionFlowPause()
const { closeModal } = useModal()

return (
<>
<ModalHeader pb={6} textAlign="center">
Paused
</ModalHeader>
<ModalBody textAlign="start" py={6} mx={3} gap={4}>
<HStack position="relative" justifyContent="center">
<Spinner size="2xl" />
<PauseIcon position="absolute" boxSize={6} color="brand.400" />
</HStack>

<TextMd>Are your sure you want to cancel?</TextMd>
</ModalBody>
<ModalFooter flexDirection="column" gap={2}>
<Button size="lg" width="100%" onClick={handleResume}>
Resume deposit
</Button>
<Button size="lg" width="100%" variant="outline" onClick={closeModal}>
Yes, cancel
</Button>
</ModalFooter>
</>
)
}
1 change: 1 addition & 0 deletions dapp/src/hooks/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export * from "./useActionFlowTxHash"
export * from "./useCompletedActivities"
export * from "./useLatestActivities"
export * from "./useAllActivitiesCount"
export * from "./useActionFlowPause"
29 changes: 29 additions & 0 deletions dapp/src/hooks/store/useActionFlowPause.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { setStatus } from "#/store/action-flow"
import { PROCESS_STATUSES } from "#/types"
import { useAppDispatch } from "./useAppDispatch"

/**
* Custom hook that provides functions to pause and resume the action flow process.
* @returns An object containing the `handlePause` and `handleResume` functions.
*/
export function useActionFlowPause() {
const dispatch = useAppDispatch()

/**
* Function to pause the action flow process.
* It dispatches an action to set the status to "PAUSED" if the current status is "PENDING".
*/
const handlePause = () => {
dispatch(setStatus(PROCESS_STATUSES.PAUSED))
}

/**
* Function to resume the action flow process.
* It dispatches an action to set the status to "PENDING".
*/
const handleResume = () => {
dispatch(setStatus(PROCESS_STATUSES.PENDING))
}

return { handlePause, handleResume }
}
6 changes: 6 additions & 0 deletions dapp/src/theme/Spinner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,14 @@ const sizeXl = defineStyle({
height: 16,
})

const size2Xl = defineStyle({
width: 20,
height: 20,
})

const sizes = {
xl: sizeXl,
"2xl": size2Xl,
}

export const spinnerTheme = defineStyleConfig({ baseStyle, sizes })
2 changes: 2 additions & 0 deletions dapp/src/types/action-flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export const PROCESS_STATUSES = {
LOADING: "LOADING",
FAILED: "FAILED",
SUCCEEDED: "SUCCEEDED",
PAUSED: "PAUSED",
PENDING: "PENDING",
} as const

export type ProcessStatus =
Expand Down
6 changes: 6 additions & 0 deletions dapp/src/types/ledger-live-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,9 @@ export type UseRequestAccountReturn = {
account: Account | null
requestAccount: (...params: RequestAccountParams) => Promise<void>
}

export type LedgerLiveError = {
message?: string
name?: string
stack?: string
}
1 change: 1 addition & 0 deletions dapp/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ export * from "./exchangeApi"
export * from "./verifyDepositAddress"
export * from "./json"
export * from "./activities"
export * from "./type-check"
15 changes: 15 additions & 0 deletions dapp/src/utils/type-check.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { LedgerLiveError } from "#/types"

export function isObject(
arg: unknown,
): arg is Record<string | number | symbol, unknown> {
return typeof arg === "object" && arg !== null
}

export function isString(arg: unknown): arg is string {
return typeof arg === "string"
}

export function isLedgerLiveError(arg: unknown): arg is LedgerLiveError {
return isObject(arg) && arg.name === "Error" && isString(arg.message)
}
Loading