Skip to content

Commit

Permalink
Merge pull request #570 from threshold-network/display-redemptions-in…
Browse files Browse the repository at this point in the history
…-my-activity

Display redemptions in my activity

Adds support for fetching pending/completed redemptions and displaying them
under the `my activity` table on the Bridge page.
  • Loading branch information
michalsmiarowski authored Jul 14, 2023
2 parents 01b624f + 434e558 commit 3dd89f7
Show file tree
Hide file tree
Showing 12 changed files with 379 additions and 38 deletions.
2 changes: 2 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import { useSubscribeToDepositRevealedEvent } from "./hooks/tbtc/useSubsribeToDe
import {
useSubscribeToOptimisticMintingFinalizedEvent,
useSubscribeToOptimisticMintingRequestedEvent,
useSubscribeToRedemptionRequestedEvent,
} from "./hooks/tbtc"
import { useSentry } from "./hooks/sentry"

Expand All @@ -80,6 +81,7 @@ const Web3EventHandlerComponent = () => {
useSubscribeToDepositRevealedEvent()
useSubscribeToOptimisticMintingFinalizedEvent()
useSubscribeToOptimisticMintingRequestedEvent()
useSubscribeToRedemptionRequestedEvent()

return <></>
}
Expand Down
32 changes: 29 additions & 3 deletions src/components/tBTC/BridgeActivity.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { FC, createContext, useContext, ReactElement } from "react"
import { useWeb3React } from "@web3-react/core"
import {
Badge,
BodyMd,
Expand All @@ -18,12 +19,14 @@ import {
import {
BridgeActivityStatus,
BridgeActivity as BridgeActivityType,
UnminBridgeActivityAdditionalData,
} from "../../threshold-ts/tbtc"
import emptyHistoryImageSrcDark from "../../static/images/tBTC-bridge-no-history-dark.svg"
import emptyHistoryImageSrcLight from "../../static/images/tBTC-bridge-no-history-light.svg"
import { InlineTokenBalance } from "../TokenBalance"
import Link from "../Link"
import { OutlineListItem } from "../OutlineListItem"
import { RedemptionDetailsLinkBuilder } from "../../utils/tBTC"

export type BridgeActivityProps = {
data: BridgeActivityType[]
Expand Down Expand Up @@ -97,16 +100,36 @@ export const BridgeActivityData: FC<ListProps> = (props) => {
const ActivityItem: FC<BridgeActivityType> = ({
amount,
status,
depositKey,
activityKey,
bridgeProcess,
additionalData,
txHash,
}) => {
const { account } = useWeb3React()

const link =
bridgeProcess === "unmint"
? RedemptionDetailsLinkBuilder.createFromTxHash(txHash)
.withRedeemer(account!)
.withRedeemerOutputScript(
(additionalData as UnminBridgeActivityAdditionalData)
.redeemerOutputScript
)
.withWalletPublicKeyHash(
(additionalData as UnminBridgeActivityAdditionalData)
.walletPublicKeyHash
)
.build()
: `/tBTC/mint/deposit/${activityKey}`

return (
<ActivityItemWrapper>
<LinkOverlay
as={Link}
textDecoration="none"
_hover={{ textDecoration: "none" }}
color="inherit"
to={`/tBTC/mint/deposit/${depositKey}`}
to={link}
>
<InlineTokenBalance tokenAmount={amount} />
</LinkOverlay>
Expand All @@ -116,7 +139,7 @@ const ActivityItem: FC<BridgeActivityType> = ({
}

const renderActivityItem = (item: BridgeActivityType) => (
<ActivityItem key={item.depositKey} {...item} />
<ActivityItem key={`${item.activityKey}-${item.txHash}`} {...item} />
)

const bridgeActivityStatusToBadgeProps: Record<
Expand All @@ -126,6 +149,9 @@ const bridgeActivityStatusToBadgeProps: Record<
[BridgeActivityStatus.MINTED]: {
colorScheme: "green",
},
[BridgeActivityStatus.UNMINTED]: {
colorScheme: "green",
},
[BridgeActivityStatus.PENDING]: {
colorScheme: "yellow",
},
Expand Down
1 change: 1 addition & 0 deletions src/hooks/tbtc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export * from "./useFetchDepositDetails"
export * from "./useFetchRecentDeposits"
export * from "./useFetchTBTCMetrics"
export * from "./useRequestRedemption"
export * from "./useSubscribeToRedemptionRequestedEvent"
49 changes: 49 additions & 0 deletions src/hooks/tbtc/useSubscribeToRedemptionRequestedEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { useWeb3React } from "@web3-react/core"
import { useSubscribeToContractEvent } from "../../web3/hooks"
import { isSameETHAddress } from "../../web3/utils"
import { useAppDispatch } from "../store"
import { useBridgeContract } from "./useBridgeContract"
import { tbtcSlice } from "../../store/tbtc"
import { BigNumber, Event } from "ethers"
import { useThreshold } from "../../contexts/ThresholdContext"
import { fromSatoshiToTokenPrecision } from "../../threshold-ts/utils"

export const useSubscribeToRedemptionRequestedEvent = () => {
const contract = useBridgeContract()
const dispatch = useAppDispatch()
const { account } = useWeb3React()
const threshold = useThreshold()

useSubscribeToContractEvent(
contract,
"RedemptionRequested",
//@ts-ignore
async (
walletPublicKeyHash: string,
redeemerOutputScript: string,
redeemer: string,
requestedAmount: BigNumber,
treasuryFee: BigNumber,
txMaxFee: BigNumber,
event: Event
) => {
if (!account || !isSameETHAddress(redeemer, account)) return

const redemptionKey = threshold.tbtc.buildRedemptionKey(
walletPublicKeyHash,
redeemerOutputScript
)

dispatch(
tbtcSlice.actions.redemptionRequested({
amount: fromSatoshiToTokenPrecision(requestedAmount).toString(),
txHash: event.transactionHash,
redemptionKey,
blockNumber: event.blockNumber,
additionalData: { redeemerOutputScript, walletPublicKeyHash },
})
)
},
[null, null, account]
)
}
1 change: 1 addition & 0 deletions src/hooks/tbtc/useSubsribeToDepositRevealedEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export const useSubscribeToDepositRevealedEvent = () => {
txHash: event.transactionHash,
depositor: depositor,
depositKey: depositKeyFromEvent,
blockNumber: event.blockNumber,
})
)
},
Expand Down
78 changes: 74 additions & 4 deletions src/store/tbtc/tbtcSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { createSlice } from "@reduxjs/toolkit"
import { PayloadAction } from "@reduxjs/toolkit/dist/createAction"
import { MintingStep, TbtcStateKey, TbtcState } from "../../types/tbtc"
import { UpdateStateActionPayload } from "../../types/state"
import { BridgeActivityStatus, BridgeActivity } from "../../threshold-ts/tbtc"
import {
BridgeActivityStatus,
BridgeActivity,
UnminBridgeActivityAdditionalData,
} from "../../threshold-ts/tbtc"
import { featureFlags } from "../../constants"
import { startAppListening } from "../listener"
import {
Expand Down Expand Up @@ -54,9 +58,10 @@ export const tbtcSlice = createSlice({
amount: string
depositor: string
txHash: string
blockNumber: number
}>
) => {
const { amount, txHash, depositKey } = action.payload
const { amount, txHash, depositKey, blockNumber } = action.payload
const history = state.bridgeActivity.data
const { itemToUpdate } = findActivityByDepositKey(history, depositKey)

Expand All @@ -66,7 +71,14 @@ export const tbtcSlice = createSlice({

// Add item only if there is no item with the same deposit key.
state.bridgeActivity.data = [
{ amount, txHash, status: BridgeActivityStatus.PENDING, depositKey },
{
amount,
txHash,
status: BridgeActivityStatus.PENDING,
activityKey: depositKey,
bridgeProcess: "mint",
blockNumber,
},
...state.bridgeActivity.data,
]
},
Expand Down Expand Up @@ -108,6 +120,45 @@ export const tbtcSlice = createSlice({
}
}>
) => {},
redemptionRequested: (
state,
action: PayloadAction<{
redemptionKey: string
blockNumber: number
amount: string
txHash: string
additionalData: UnminBridgeActivityAdditionalData
}>
) => {
const {
payload: { amount, redemptionKey, blockNumber, txHash, additionalData },
} = action

const { itemToUpdate } = findRedemptionActivity(
state.bridgeActivity.data,
redemptionKey,
txHash
)

// Do not update an array if there is already an item with the same
// redemption key and transaction hash- just in case duplicated Ethereum
// events.
if (itemToUpdate) return

// Add item only if there is no item with the same deposit key.
state.bridgeActivity.data = [
{
amount,
txHash,
status: BridgeActivityStatus.PENDING,
activityKey: redemptionKey,
bridgeProcess: "unmint",
blockNumber,
additionalData,
},
...state.bridgeActivity.data,
]
},
},
})

Expand All @@ -116,7 +167,26 @@ function findActivityByDepositKey(
depositKey: string
) {
const activityIndexItemToUpdate = bridgeActivities.findIndex(
(item) => item.depositKey === depositKey
(item) => item.activityKey === depositKey
)

if (activityIndexItemToUpdate < 0) return { index: -1, itemToUpdate: null }

const activityItemToUpdate = bridgeActivities[activityIndexItemToUpdate]

return {
index: activityIndexItemToUpdate,
itemToUpdate: activityItemToUpdate,
}
}

function findRedemptionActivity(
bridgeActivities: BridgeActivity[],
redemptionKey: string,
txHash: string
) {
const activityIndexItemToUpdate = bridgeActivities.findIndex(
(item) => item.activityKey === redemptionKey && item.txHash === txHash
)

if (activityIndexItemToUpdate < 0) return { index: -1, itemToUpdate: null }
Expand Down
Loading

0 comments on commit 3dd89f7

Please sign in to comment.