Skip to content

Commit 3dd89f7

Browse files
Merge pull request #570 from threshold-network/display-redemptions-in-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.
2 parents 01b624f + 434e558 commit 3dd89f7

File tree

12 files changed

+379
-38
lines changed

12 files changed

+379
-38
lines changed

src/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ import { useSubscribeToDepositRevealedEvent } from "./hooks/tbtc/useSubsribeToDe
5555
import {
5656
useSubscribeToOptimisticMintingFinalizedEvent,
5757
useSubscribeToOptimisticMintingRequestedEvent,
58+
useSubscribeToRedemptionRequestedEvent,
5859
} from "./hooks/tbtc"
5960
import { useSentry } from "./hooks/sentry"
6061

@@ -80,6 +81,7 @@ const Web3EventHandlerComponent = () => {
8081
useSubscribeToDepositRevealedEvent()
8182
useSubscribeToOptimisticMintingFinalizedEvent()
8283
useSubscribeToOptimisticMintingRequestedEvent()
84+
useSubscribeToRedemptionRequestedEvent()
8385

8486
return <></>
8587
}

src/components/tBTC/BridgeActivity.tsx

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { FC, createContext, useContext, ReactElement } from "react"
2+
import { useWeb3React } from "@web3-react/core"
23
import {
34
Badge,
45
BodyMd,
@@ -18,12 +19,14 @@ import {
1819
import {
1920
BridgeActivityStatus,
2021
BridgeActivity as BridgeActivityType,
22+
UnminBridgeActivityAdditionalData,
2123
} from "../../threshold-ts/tbtc"
2224
import emptyHistoryImageSrcDark from "../../static/images/tBTC-bridge-no-history-dark.svg"
2325
import emptyHistoryImageSrcLight from "../../static/images/tBTC-bridge-no-history-light.svg"
2426
import { InlineTokenBalance } from "../TokenBalance"
2527
import Link from "../Link"
2628
import { OutlineListItem } from "../OutlineListItem"
29+
import { RedemptionDetailsLinkBuilder } from "../../utils/tBTC"
2730

2831
export type BridgeActivityProps = {
2932
data: BridgeActivityType[]
@@ -97,16 +100,36 @@ export const BridgeActivityData: FC<ListProps> = (props) => {
97100
const ActivityItem: FC<BridgeActivityType> = ({
98101
amount,
99102
status,
100-
depositKey,
103+
activityKey,
104+
bridgeProcess,
105+
additionalData,
106+
txHash,
101107
}) => {
108+
const { account } = useWeb3React()
109+
110+
const link =
111+
bridgeProcess === "unmint"
112+
? RedemptionDetailsLinkBuilder.createFromTxHash(txHash)
113+
.withRedeemer(account!)
114+
.withRedeemerOutputScript(
115+
(additionalData as UnminBridgeActivityAdditionalData)
116+
.redeemerOutputScript
117+
)
118+
.withWalletPublicKeyHash(
119+
(additionalData as UnminBridgeActivityAdditionalData)
120+
.walletPublicKeyHash
121+
)
122+
.build()
123+
: `/tBTC/mint/deposit/${activityKey}`
124+
102125
return (
103126
<ActivityItemWrapper>
104127
<LinkOverlay
105128
as={Link}
106129
textDecoration="none"
107130
_hover={{ textDecoration: "none" }}
108131
color="inherit"
109-
to={`/tBTC/mint/deposit/${depositKey}`}
132+
to={link}
110133
>
111134
<InlineTokenBalance tokenAmount={amount} />
112135
</LinkOverlay>
@@ -116,7 +139,7 @@ const ActivityItem: FC<BridgeActivityType> = ({
116139
}
117140

118141
const renderActivityItem = (item: BridgeActivityType) => (
119-
<ActivityItem key={item.depositKey} {...item} />
142+
<ActivityItem key={`${item.activityKey}-${item.txHash}`} {...item} />
120143
)
121144

122145
const bridgeActivityStatusToBadgeProps: Record<
@@ -126,6 +149,9 @@ const bridgeActivityStatusToBadgeProps: Record<
126149
[BridgeActivityStatus.MINTED]: {
127150
colorScheme: "green",
128151
},
152+
[BridgeActivityStatus.UNMINTED]: {
153+
colorScheme: "green",
154+
},
129155
[BridgeActivityStatus.PENDING]: {
130156
colorScheme: "yellow",
131157
},

src/hooks/tbtc/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ export * from "./useFetchDepositDetails"
88
export * from "./useFetchRecentDeposits"
99
export * from "./useFetchTBTCMetrics"
1010
export * from "./useRequestRedemption"
11+
export * from "./useSubscribeToRedemptionRequestedEvent"
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { useWeb3React } from "@web3-react/core"
2+
import { useSubscribeToContractEvent } from "../../web3/hooks"
3+
import { isSameETHAddress } from "../../web3/utils"
4+
import { useAppDispatch } from "../store"
5+
import { useBridgeContract } from "./useBridgeContract"
6+
import { tbtcSlice } from "../../store/tbtc"
7+
import { BigNumber, Event } from "ethers"
8+
import { useThreshold } from "../../contexts/ThresholdContext"
9+
import { fromSatoshiToTokenPrecision } from "../../threshold-ts/utils"
10+
11+
export const useSubscribeToRedemptionRequestedEvent = () => {
12+
const contract = useBridgeContract()
13+
const dispatch = useAppDispatch()
14+
const { account } = useWeb3React()
15+
const threshold = useThreshold()
16+
17+
useSubscribeToContractEvent(
18+
contract,
19+
"RedemptionRequested",
20+
//@ts-ignore
21+
async (
22+
walletPublicKeyHash: string,
23+
redeemerOutputScript: string,
24+
redeemer: string,
25+
requestedAmount: BigNumber,
26+
treasuryFee: BigNumber,
27+
txMaxFee: BigNumber,
28+
event: Event
29+
) => {
30+
if (!account || !isSameETHAddress(redeemer, account)) return
31+
32+
const redemptionKey = threshold.tbtc.buildRedemptionKey(
33+
walletPublicKeyHash,
34+
redeemerOutputScript
35+
)
36+
37+
dispatch(
38+
tbtcSlice.actions.redemptionRequested({
39+
amount: fromSatoshiToTokenPrecision(requestedAmount).toString(),
40+
txHash: event.transactionHash,
41+
redemptionKey,
42+
blockNumber: event.blockNumber,
43+
additionalData: { redeemerOutputScript, walletPublicKeyHash },
44+
})
45+
)
46+
},
47+
[null, null, account]
48+
)
49+
}

src/hooks/tbtc/useSubsribeToDepositRevealedEvent.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ export const useSubscribeToDepositRevealedEvent = () => {
6161
txHash: event.transactionHash,
6262
depositor: depositor,
6363
depositKey: depositKeyFromEvent,
64+
blockNumber: event.blockNumber,
6465
})
6566
)
6667
},

src/store/tbtc/tbtcSlice.ts

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ import { createSlice } from "@reduxjs/toolkit"
22
import { PayloadAction } from "@reduxjs/toolkit/dist/createAction"
33
import { MintingStep, TbtcStateKey, TbtcState } from "../../types/tbtc"
44
import { UpdateStateActionPayload } from "../../types/state"
5-
import { BridgeActivityStatus, BridgeActivity } from "../../threshold-ts/tbtc"
5+
import {
6+
BridgeActivityStatus,
7+
BridgeActivity,
8+
UnminBridgeActivityAdditionalData,
9+
} from "../../threshold-ts/tbtc"
610
import { featureFlags } from "../../constants"
711
import { startAppListening } from "../listener"
812
import {
@@ -54,9 +58,10 @@ export const tbtcSlice = createSlice({
5458
amount: string
5559
depositor: string
5660
txHash: string
61+
blockNumber: number
5762
}>
5863
) => {
59-
const { amount, txHash, depositKey } = action.payload
64+
const { amount, txHash, depositKey, blockNumber } = action.payload
6065
const history = state.bridgeActivity.data
6166
const { itemToUpdate } = findActivityByDepositKey(history, depositKey)
6267

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

6772
// Add item only if there is no item with the same deposit key.
6873
state.bridgeActivity.data = [
69-
{ amount, txHash, status: BridgeActivityStatus.PENDING, depositKey },
74+
{
75+
amount,
76+
txHash,
77+
status: BridgeActivityStatus.PENDING,
78+
activityKey: depositKey,
79+
bridgeProcess: "mint",
80+
blockNumber,
81+
},
7082
...state.bridgeActivity.data,
7183
]
7284
},
@@ -108,6 +120,45 @@ export const tbtcSlice = createSlice({
108120
}
109121
}>
110122
) => {},
123+
redemptionRequested: (
124+
state,
125+
action: PayloadAction<{
126+
redemptionKey: string
127+
blockNumber: number
128+
amount: string
129+
txHash: string
130+
additionalData: UnminBridgeActivityAdditionalData
131+
}>
132+
) => {
133+
const {
134+
payload: { amount, redemptionKey, blockNumber, txHash, additionalData },
135+
} = action
136+
137+
const { itemToUpdate } = findRedemptionActivity(
138+
state.bridgeActivity.data,
139+
redemptionKey,
140+
txHash
141+
)
142+
143+
// Do not update an array if there is already an item with the same
144+
// redemption key and transaction hash- just in case duplicated Ethereum
145+
// events.
146+
if (itemToUpdate) return
147+
148+
// Add item only if there is no item with the same deposit key.
149+
state.bridgeActivity.data = [
150+
{
151+
amount,
152+
txHash,
153+
status: BridgeActivityStatus.PENDING,
154+
activityKey: redemptionKey,
155+
bridgeProcess: "unmint",
156+
blockNumber,
157+
additionalData,
158+
},
159+
...state.bridgeActivity.data,
160+
]
161+
},
111162
},
112163
})
113164

@@ -116,7 +167,26 @@ function findActivityByDepositKey(
116167
depositKey: string
117168
) {
118169
const activityIndexItemToUpdate = bridgeActivities.findIndex(
119-
(item) => item.depositKey === depositKey
170+
(item) => item.activityKey === depositKey
171+
)
172+
173+
if (activityIndexItemToUpdate < 0) return { index: -1, itemToUpdate: null }
174+
175+
const activityItemToUpdate = bridgeActivities[activityIndexItemToUpdate]
176+
177+
return {
178+
index: activityIndexItemToUpdate,
179+
itemToUpdate: activityItemToUpdate,
180+
}
181+
}
182+
183+
function findRedemptionActivity(
184+
bridgeActivities: BridgeActivity[],
185+
redemptionKey: string,
186+
txHash: string
187+
) {
188+
const activityIndexItemToUpdate = bridgeActivities.findIndex(
189+
(item) => item.activityKey === redemptionKey && item.txHash === txHash
120190
)
121191

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

0 commit comments

Comments
 (0)