diff --git a/dapp/src/components/TransactionModal/ActiveStakingStep/StakeFormModal/StakeDetails.tsx b/dapp/src/components/TransactionModal/ActiveStakingStep/StakeFormModal/StakeDetails.tsx
index 9f6d8ebf3..6fc73f611 100644
--- a/dapp/src/components/TransactionModal/ActiveStakingStep/StakeFormModal/StakeDetails.tsx
+++ b/dapp/src/components/TransactionModal/ActiveStakingStep/StakeFormModal/StakeDetails.tsx
@@ -1,9 +1,23 @@
import React from "react"
import { List } from "@chakra-ui/react"
import TransactionDetailsAmountItem from "#/components/shared/TransactionDetails/AmountItem"
+import FeesDetailsAmountItem from "#/components/shared/FeesDetails/FeesItem"
import { useTokenAmountFormValue } from "#/components/shared/TokenAmountForm/TokenAmountFormBase"
+import { FeesTooltip } from "#/components/TransactionModal/FeesTooltip"
import { useTransactionDetails } from "#/hooks"
-import { CurrencyType } from "#/types"
+import { CurrencyType, DepositFee } from "#/types"
+import { useTransactionFee } from "#/hooks/useTransactionFee"
+
+const mapDepositFeeToLabel = (feeId: keyof DepositFee) => {
+ switch (feeId) {
+ case "acre":
+ return "Acre protocol fees"
+ case "tbtc":
+ return "tBTC bridge fees"
+ default:
+ return ""
+ }
+}
function StakeDetails({
currency,
@@ -20,6 +34,7 @@ function StakeDetails({
// Let's not calculate the details of the transaction when the value is not valid.
const amount = !isMaximumValueExceeded && isMinimumValueFulfilled ? value : 0n
const details = useTransactionDetails(amount)
+ const { total, ...restFees } = useTransactionFee(amount)
return (
@@ -33,11 +48,17 @@ function StakeDetails({
currency: "usd",
}}
/>
-
+ }
from={{
currency,
- amount: details?.protocolFee,
+ amount: total,
}}
to={{
currency: "usd",
diff --git a/dapp/src/components/TransactionModal/ActiveUnstakingStep/UnstakeFormModal/UnstakeDetails.tsx b/dapp/src/components/TransactionModal/ActiveUnstakingStep/UnstakeFormModal/UnstakeDetails.tsx
index 850f88561..844fe9c43 100644
--- a/dapp/src/components/TransactionModal/ActiveUnstakingStep/UnstakeFormModal/UnstakeDetails.tsx
+++ b/dapp/src/components/TransactionModal/ActiveUnstakingStep/UnstakeFormModal/UnstakeDetails.tsx
@@ -21,16 +21,19 @@ function UnstakeDetails({ currency }: { currency: CurrencyType }) {
currency: "usd",
}}
/>
- }
from={{
currency,
- amount: details?.protocolFee,
+ amount: transactionFee.total,
}}
to={{
currency: "usd",
}}
- />
+ /> */}
= {
+ fees: F
+ mapFeeToLabel: (feeName: keyof F) => string
+}
+
+export function FeesTooltip({ fees, mapFeeToLabel }: Props) {
+ return (
+
+ {Object.entries(fees).map(([feeKey, feeValue]) => (
+
+ ))}
+
+ }
+ >
+
+
+ )
+}
diff --git a/dapp/src/components/TransactionModal/FeesTooltip/FeesTooltipItem.tsx b/dapp/src/components/TransactionModal/FeesTooltip/FeesTooltipItem.tsx
new file mode 100644
index 000000000..3250ffc80
--- /dev/null
+++ b/dapp/src/components/TransactionModal/FeesTooltip/FeesTooltipItem.tsx
@@ -0,0 +1,27 @@
+import React from "react"
+import { ListItem } from "@chakra-ui/react"
+import {
+ CurrencyBalance,
+ CurrencyBalanceProps,
+} from "#/components/shared/CurrencyBalance"
+import { TextSm } from "#/components/shared/Typography"
+
+export type FeesItemType = CurrencyBalanceProps & {
+ label: string
+}
+
+export function FeesTooltipItem({ label, amount, ...props }: FeesItemType) {
+ return (
+
+ {label}
+
+
+ )
+}
diff --git a/dapp/src/components/TransactionModal/FeesTooltip/index.ts b/dapp/src/components/TransactionModal/FeesTooltip/index.ts
new file mode 100644
index 000000000..9d08672e3
--- /dev/null
+++ b/dapp/src/components/TransactionModal/FeesTooltip/index.ts
@@ -0,0 +1 @@
+export * from "./FeesTooltip"
diff --git a/dapp/src/components/shared/FeesDetails/FeesItem.tsx b/dapp/src/components/shared/FeesDetails/FeesItem.tsx
new file mode 100644
index 000000000..6697e7d6d
--- /dev/null
+++ b/dapp/src/components/shared/FeesDetails/FeesItem.tsx
@@ -0,0 +1,43 @@
+import React, { ComponentProps } from "react"
+import { Flex } from "@chakra-ui/react"
+import FeesDetailsItem, { FeesDetailsItemProps } from "."
+import { CurrencyBalanceWithConversion } from "../CurrencyBalanceWithConversion"
+
+type FeesDetailsItemAmountItemProps = ComponentProps<
+ typeof CurrencyBalanceWithConversion
+> &
+ Pick
+
+function FeesDetailsAmountItem({
+ label,
+ sublabel,
+ tooltip,
+ from,
+ to,
+}: FeesDetailsItemAmountItemProps) {
+ return (
+
+
+
+
+
+ )
+}
+
+export default FeesDetailsAmountItem
diff --git a/dapp/src/components/shared/FeesDetails/index.tsx b/dapp/src/components/shared/FeesDetails/index.tsx
new file mode 100644
index 000000000..c9e0a6028
--- /dev/null
+++ b/dapp/src/components/shared/FeesDetails/index.tsx
@@ -0,0 +1,45 @@
+import React from "react"
+import { ListItem, ListItemProps, VStack } from "@chakra-ui/react"
+import { TextMd, TextSm } from "../Typography"
+
+export type FeesDetailsItemProps = {
+ label: string
+ sublabel: string
+ value?: string
+ tooltip: React.ReactElement
+ children?: React.ReactNode
+} & ListItemProps
+
+function FeesDetailsItem({
+ label,
+ sublabel,
+ tooltip,
+ value,
+ children,
+ ...listItemProps
+}: FeesDetailsItemProps) {
+ return (
+
+
+
+ {label}
+ {tooltip}
+
+ {sublabel && {sublabel}}
+
+ {value ? {value} : children}
+
+ )
+}
+
+export default FeesDetailsItem
diff --git a/dapp/src/hooks/index.ts b/dapp/src/hooks/index.ts
index 5651557f2..1c483932d 100644
--- a/dapp/src/hooks/index.ts
+++ b/dapp/src/hooks/index.ts
@@ -23,3 +23,4 @@ export * from "./useTimeout"
export * from "./useCountdown"
export * from "./useActivities"
export * from "./useSize"
+export * from "./useTransactionFee"
diff --git a/dapp/src/hooks/useTransactionFee.ts b/dapp/src/hooks/useTransactionFee.ts
new file mode 100644
index 000000000..b650d7fbe
--- /dev/null
+++ b/dapp/src/hooks/useTransactionFee.ts
@@ -0,0 +1,33 @@
+import { useAcreContext } from "#/acre-react/hooks"
+import { logPromiseFailure } from "#/utils"
+import { useEffect, useState } from "react"
+import { DepositFee } from "#/types"
+import { useAppDispatch } from "./store"
+
+const initialDepositFee = {
+ tbtc: 0n,
+ acre: 0n,
+ total: 0n,
+}
+
+export function useTransactionFee(amount?: bigint) {
+ const [depositFee, setDepositFee] = useState(initialDepositFee)
+ const { acre } = useAcreContext()
+ const dispatch = useAppDispatch()
+
+ useEffect(() => {
+ if (!amount) {
+ setDepositFee(initialDepositFee)
+ } else {
+ const getEstimatedDepositFee = async () => {
+ if (!acre) return
+ const fee = await acre.staking.estimateDepositFee(amount)
+
+ setDepositFee(fee)
+ }
+ logPromiseFailure(getEstimatedDepositFee())
+ }
+ }, [acre, dispatch, amount])
+
+ return depositFee
+}
diff --git a/dapp/src/types/fee.ts b/dapp/src/types/fee.ts
new file mode 100644
index 000000000..e35b33004
--- /dev/null
+++ b/dapp/src/types/fee.ts
@@ -0,0 +1,5 @@
+export type DepositFee = {
+ tbtc: bigint
+ acre: bigint
+ total: bigint
+}
diff --git a/dapp/src/types/index.ts b/dapp/src/types/index.ts
index 16d93da3b..b3b047b18 100644
--- a/dapp/src/types/index.ts
+++ b/dapp/src/types/index.ts
@@ -13,3 +13,4 @@ export * from "./coingecko"
export * from "./time"
export * from "./size"
export * from "./toast"
+export * from "./fee"