Skip to content

Commit

Permalink
Merge branch 'main' into deposit-history
Browse files Browse the repository at this point in the history
  • Loading branch information
r-czajkowski committed May 29, 2024
2 parents c8c8bbb + 3c68902 commit ff637eb
Show file tree
Hide file tree
Showing 32 changed files with 484 additions and 148 deletions.
23 changes: 7 additions & 16 deletions dapp/src/acre-react/contexts/AcreSdkContext.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useCallback, useMemo, useState } from "react"
import { Acre, BitcoinNetwork } from "@acre-btc/sdk"
import { Acre } from "@acre-btc/sdk"
import { BitcoinProvider } from "@acre-btc/sdk/dist/src/lib/bitcoin/providers"
import { BITCOIN_NETWORK } from "#/constants"

Expand All @@ -24,21 +24,12 @@ export function AcreSdkProvider({ children }: { children: React.ReactNode }) {

const init = useCallback<AcreSdkContextValue["init"]>(
async (bitcoinProvider: BitcoinProvider) => {
let sdk: Acre

if (BITCOIN_NETWORK === BitcoinNetwork.Mainnet) {
sdk = await Acre.initializeMainnet(
bitcoinProvider,
TBTC_API_ENDPOINT,
ETH_RPC_URL,
)
} else {
sdk = await Acre.initializeTestnet(
bitcoinProvider,
TBTC_API_ENDPOINT,
ETH_RPC_URL,
)
}
const sdk: Acre = await Acre.initialize(
BITCOIN_NETWORK,
bitcoinProvider,
TBTC_API_ENDPOINT,
ETH_RPC_URL,
)

setAcre(sdk)
setIsInitialized(true)
Expand Down
13 changes: 5 additions & 8 deletions dapp/src/assets/icons/animated/ArrowUpRightAnimatedIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react"
import { ArrowUpRight } from "#/assets/icons"
import { Box, Icon } from "@chakra-ui/react"
import { Box, BoxProps, Icon } from "@chakra-ui/react"
import { Variants, motion } from "framer-motion"
import { chakraUnitToPx } from "#/theme/utils"

Expand Down Expand Up @@ -34,18 +34,15 @@ const arrowBottomVariants: Variants = {
}),
}

type ArrowUpRightAnimatedIconProps = {
type ArrowUpRightAnimatedIconProps = BoxProps & {
boxSize?: number
color?: string
}

export function ArrowUpRightAnimatedIcon({
boxSize = 4,
color = "brand.400",
}: ArrowUpRightAnimatedIconProps) {
export function ArrowUpRightAnimatedIcon(props: ArrowUpRightAnimatedIconProps) {
const { boxSize = 4, color = "inherit", ...restProps } = props
const boxSizePx = chakraUnitToPx(boxSize)
return (
<Box pos="relative" boxSize={boxSize} overflow="hidden">
<Box pos="relative" boxSize={boxSize} overflow="hidden" {...restProps}>
{[
{ id: "arrow-up", variants: arrowUpVariants },
{ id: "arrow-bottom", variants: arrowBottomVariants },
Expand Down
Binary file added dapp/src/assets/images/empty-state.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const PAGINATION_BUTTONS = [
},
]

// TODO: move to top level `utils` directory
export const getPaginationState = (
pageIndex: number,
pageSize: number,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback } from "react"
import React, { useCallback, useEffect } from "react"
import {
useActionFlowTokenAmount,
useAppDispatch,
Expand All @@ -18,7 +18,7 @@ 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"
import { setStatus, setTxHash } from "#/store/action-flow"

const DELAY = ONE_SEC_IN_MILLISECONDS
const TOAST_ID = TOAST_IDS.DEPOSIT_TRANSACTION_ERROR
Expand Down Expand Up @@ -64,11 +64,17 @@ export default function DepositBTCModal() {

const onDepositBTCError = useCallback(() => showError(), [showError])

const { sendBitcoinTransaction } = useDepositBTCTransaction(
const { sendBitcoinTransaction, transactionHash } = useDepositBTCTransaction(
onDepositBTCSuccess,
onDepositBTCError,
)

useEffect(() => {
if (transactionHash) {
dispatch(setTxHash(transactionHash))
}
}, [dispatch, transactionHash])

const handledDepositBTC = useCallback(async () => {
if (!tokenAmount?.amount || !btcAddress || !depositReceipt || !ethAccount)
return
Expand Down
8 changes: 6 additions & 2 deletions dapp/src/components/TransactionModal/ModalContentWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from "react"
import {
useActionFlowStatus,
useActionFlowTokenAmount,
useActionFlowTxHash,
useActionFlowType,
useRequestBitcoinAccount,
useWalletContext,
Expand All @@ -25,6 +26,7 @@ export default function ModalContentWrapper({
const status = useActionFlowStatus()
const type = useActionFlowType()
const tokenAmount = useActionFlowTokenAmount()
const txHash = useActionFlowTxHash()

if (!btcAccount || !isSupportedBTCAddressType(btcAccount.address))
return (
Expand All @@ -39,8 +41,10 @@ export default function ModalContentWrapper({

if (status === PROCESS_STATUSES.LOADING) return <LoadingModal />

if (status === PROCESS_STATUSES.SUCCEEDED)
return <SuccessModal type={type} tokenAmount={tokenAmount} />
if (status === PROCESS_STATUSES.SUCCEEDED && txHash)
return (
<SuccessModal type={type} tokenAmount={tokenAmount} txHash={txHash} />
)

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

Expand Down
42 changes: 35 additions & 7 deletions dapp/src/components/TransactionModal/SuccessModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from "react"
import {
Button,
HStack,
Icon,
ModalBody,
ModalFooter,
ModalHeader,
Expand All @@ -11,6 +12,9 @@ import { LoadingSpinnerSuccessIcon } from "#/assets/icons"
import { useModal } from "#/hooks"
import { CurrencyBalanceWithConversion } from "#/components/shared/CurrencyBalanceWithConversion"
import { ACTION_FLOW_TYPES, ActionFlowType, TokenAmount } from "#/types"
import { useNavigate } from "react-router-dom"
import { routerPath } from "#/router/path"
import { IconArrowUpRight } from "@tabler/icons-react"
import { TextMd } from "../shared/Typography"
import Spinner from "../shared/Spinner"
import BlockExplorerLink from "../shared/BlockExplorerLink"
Expand All @@ -19,13 +23,13 @@ const CONTENT: Record<
ActionFlowType,
{
header: string
renderBody: (tokenAmount: TokenAmount) => React.ReactNode
renderBody: (tokenAmount: TokenAmount, txHash: string) => React.ReactNode
footer: string
}
> = {
[ACTION_FLOW_TYPES.STAKE]: {
header: "Deposit received",
renderBody: (tokenAmount) => (
renderBody: (tokenAmount, txHash) => (
<>
<VStack spacing={0}>
<CurrencyBalanceWithConversion
Expand All @@ -42,8 +46,18 @@ const CONTENT: Record<
}}
/>
</VStack>
{/* TODO: Use correct tx hash and update styles */}
<BlockExplorerLink id="" type="transaction" chain="bitcoin" mt={2} />
{/* TODO: Update styles */}
<BlockExplorerLink
id={txHash}
type="transaction"
chain="bitcoin"
mt={2}
>
<HStack gap={1}>
<TextMd fontWeight="semibold">View on Mempool</TextMd>
<Icon as={IconArrowUpRight} color="brand.400" boxSize={5} />
</HStack>
</BlockExplorerLink>
</>
),
footer: "The staking will continue in the background",
Expand All @@ -63,10 +77,16 @@ const CONTENT: Record<
type SuccessModalProps = {
type: ActionFlowType
tokenAmount: TokenAmount
txHash: string
}

export default function SuccessModal({ type, tokenAmount }: SuccessModalProps) {
export default function SuccessModal({
type,
tokenAmount,
txHash,
}: SuccessModalProps) {
const { closeModal } = useModal()
const navigate = useNavigate()

const { header, footer, renderBody } = CONTENT[type]

Expand All @@ -76,11 +96,19 @@ export default function SuccessModal({ type, tokenAmount }: SuccessModalProps) {
<ModalBody gap={10}>
<VStack gap={4}>
<LoadingSpinnerSuccessIcon boxSize={20} />
{renderBody(tokenAmount)}
{renderBody(tokenAmount, txHash)}
</VStack>
</ModalBody>
<ModalFooter pt={0}>
<Button size="lg" width="100%" variant="outline" onClick={closeModal}>
<Button
size="lg"
width="100%"
variant="outline"
onClick={() => {
closeModal()
navigate(routerPath.dashboard)
}}
>
Go to dashboard
</Button>
<HStack spacing={2}>
Expand Down
43 changes: 43 additions & 0 deletions dapp/src/components/shared/Pagination/Pagination.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from "react"
import { PaginationContext } from "#/contexts"
import { StackProps, VStack } from "@chakra-ui/react"

export type PaginationProps<T> = Omit<StackProps, "as"> & {
data: T[]
pageSize?: number
defaultPage?: number
}

function Pagination<T>(props: PaginationProps<T>) {
const { data, children, pageSize = 10, defaultPage = 0, ...restProps } = props

const [page, setPage] = React.useState(defaultPage)

const pageData = React.useMemo(() => {
const startIndex = page * pageSize
const endIndex = startIndex + pageSize

return data.slice(startIndex, endIndex)
}, [data, page, pageSize])

const contextValue = React.useMemo(
() => ({
pageSize,
page,
setPage,
totalSize: data.length,
pageData,
}),
[pageSize, page, data, pageData],
)

return (
<PaginationContext.Provider value={contextValue}>
<VStack spacing={6} align="stretch" w="full" {...restProps}>
{children}
</VStack>
</PaginationContext.Provider>
)
}

export default Pagination
43 changes: 43 additions & 0 deletions dapp/src/components/shared/Pagination/PaginationButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from "react"
import { Icon, IconButton, IconButtonProps } from "@chakra-ui/react"
import { IconArrowLeft, IconArrowRight } from "@tabler/icons-react"
import { usePagination } from "#/hooks"

type PaginationButtonProps = Omit<IconButtonProps, "aria-label" | "icon"> & {
mode: "previous" | "next"
}

function PaginationButton(props: PaginationButtonProps) {
const { mode, ...restProps } = props
const { page, setPage, totalSize, pageSize } = usePagination()

const handleClick = () => setPage(mode === "next" ? page + 1 : page - 1)
const isDisabled = React.useMemo(
() =>
mode === "next" ? page * pageSize + pageSize >= totalSize : page === 0,
[mode, page, pageSize, totalSize],
)

return (
<IconButton
variant="pagination"
rounded="full"
p={1.5}
boxSize={7}
minW="unset"
icon={
<Icon
as={mode === "next" ? IconArrowRight : IconArrowLeft}
strokeWidth={2}
boxSize={4}
/>
}
aria-label={mode === "next" ? "Next" : "Previous"}
onClick={handleClick}
isDisabled={isDisabled}
{...restProps}
/>
)
}

export default PaginationButton
75 changes: 75 additions & 0 deletions dapp/src/components/shared/Pagination/PaginationPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import React from "react"
import { Box, Stack, StackProps, useToken } from "@chakra-ui/react"
import { useSize } from "@chakra-ui/react-use-size"
import { AnimatePresence, Transition, Variants, motion } from "framer-motion"
import { usePagination } from "#/hooks"

const transition: Transition = {
type: "spring",
stiffness: 120,
damping: 16,
mass: 0.85,
}

const variants: Variants = {
enter: ({ direction, spacing }) => ({
x: `calc((100% + ${spacing}) * ${direction === "right" ? 1 : -1})`,
transition,
}),
center: {
x: 0,
transition,
},
exit: ({ direction, spacing }) => ({
x: `calc((100% + ${spacing}) * ${direction === "left" ? 1 : -1})`,
transition,
}),
}

type PaginationPageProps<T> = Omit<StackProps, "children"> & {
children: (pageData: T[]) => React.ReactNode
pageSpacing?: number | string
}

function PaginationPage<T>(props: PaginationPageProps<T>) {
const { children, pageSpacing = 0, ...restProps } = props
const { page, pageData } = usePagination()

const ref = React.useRef<HTMLDivElement>(null)
const { height } = useSize(ref) ?? { height: 0 }

const previousPage = React.useRef<number>(0)
React.useEffect(() => {
previousPage.current = page
}, [page])

const direction = page < previousPage.current ? "left" : "right"
const spacing = useToken("space", pageSpacing, "20%")

return (
<Box as={motion.div} layout animate={{ height, transition }}>
<Box ref={ref}>
<AnimatePresence
mode="popLayout"
custom={{ direction, spacing }}
initial={false}
>
<Stack
as={motion.div}
custom={{ direction, spacing }}
key={page}
variants={variants}
animate="center"
initial="enter"
exit="exit"
{...restProps}
>
{children(pageData as T[])}
</Stack>
</AnimatePresence>
</Box>
</Box>
)
}

export default PaginationPage
Loading

0 comments on commit ff637eb

Please sign in to comment.