99 type ColumnProps ,
1010} from "@babylonlabs-io/core-ui" ;
1111import { useWalletConnect } from "@babylonlabs-io/wallet-connector" ;
12- import { useMemo } from "react" ;
12+ import { useCallback , useMemo , useState } from "react" ;
1313import type { Hex } from "viem" ;
1414
1515import { useBTCWallet , useETHWallet } from "../../../../context/wallet" ;
@@ -19,6 +19,8 @@ import { getPeginState } from "../../../../models/peginStateMachine";
1919import { usePeginStorage } from "../../../../storage/usePeginStorage" ;
2020import type { VaultActivity } from "../../../../types/activity" ;
2121import type { Deposit } from "../../../../types/vault" ;
22+ import { BroadcastSignModal } from "../BroadcastSignModal" ;
23+ import { BroadcastSuccessModal } from "../BroadcastSuccessModal" ;
2224import { DepositTableRowActions } from "../DepositTableRow" ;
2325import { useDepositRowPolling } from "../hooks/useDepositRowPolling" ;
2426import { usePayoutSignModal } from "../hooks/usePayoutSignModal" ;
@@ -27,6 +29,10 @@ import {
2729 useVaultDepositState ,
2830 VaultDepositStep ,
2931} from "../state/VaultDepositState" ;
32+ import {
33+ useVaultRedeemState ,
34+ VaultRedeemStep ,
35+ } from "../state/VaultRedeemState" ;
3036
3137function EmptyState ( {
3238 onDeposit,
@@ -109,12 +115,14 @@ function ActionCell({
109115 btcPublicKey,
110116 pendingPegins,
111117 onSignClick,
118+ onBroadcastClick,
112119} : {
113120 activity : VaultActivity ;
114121 deposit : Deposit ;
115122 btcPublicKey ?: string ;
116123 pendingPegins : any [ ] ;
117124 onSignClick : ( depositId : string , transactions : any [ ] ) => void ;
125+ onBroadcastClick : ( depositId : string ) => void ;
118126} ) {
119127 const pendingPegin = pendingPegins . find ( ( p ) => p . id === deposit . id ) ;
120128
@@ -125,6 +133,7 @@ function ActionCell({
125133 btcPublicKey = { btcPublicKey }
126134 pendingPegin = { pendingPegin }
127135 onSignClick = { onSignClick }
136+ onBroadcastClick = { onBroadcastClick }
128137 />
129138 ) ;
130139}
@@ -136,20 +145,26 @@ function DepositMobileCard({
136145 btcPublicKey,
137146 pendingPegins,
138147 onSignClick,
148+ onBroadcastClick,
139149} : {
140150 deposit : Deposit ;
141151 activity : VaultActivity ;
142152 btcPublicKey ?: string ;
143153 pendingPegins : any [ ] ;
144154 onSignClick : ( depositId : string , transactions : any [ ] ) => void ;
155+ onBroadcastClick : ( depositId : string ) => void ;
145156} ) {
146157 const pendingPegin = pendingPegins . find ( ( p ) => p . id === deposit . id ) ;
147- const { peginState, shouldShowSignButton, transactions } =
148- useDepositRowPolling ( {
149- activity,
150- btcPublicKey,
151- pendingPegin,
152- } ) ;
158+ const {
159+ peginState,
160+ shouldShowSignButton,
161+ shouldShowBroadcastButton,
162+ transactions,
163+ } = useDepositRowPolling ( {
164+ activity,
165+ btcPublicKey,
166+ pendingPegin,
167+ } ) ;
153168 const status = peginState . displayLabel ;
154169
155170 const statusMap : Record < string , "inactive" | "pending" | "active" > = {
@@ -194,11 +209,17 @@ function DepositMobileCard({
194209 } ,
195210 ] }
196211 actions = {
197- shouldShowSignButton ? [ { name : "Sign" , action : "sign" } ] : undefined
212+ shouldShowSignButton
213+ ? [ { name : "Sign" , action : "sign" } ]
214+ : shouldShowBroadcastButton
215+ ? [ { name : "Sign & Broadcast" , action : "broadcast" } ]
216+ : undefined
198217 }
199218 onAction = { ( id , action ) => {
200219 if ( action === "sign" && transactions ) {
201220 onSignClick ( id , transactions ) ;
221+ } else if ( action === "broadcast" ) {
222+ onBroadcastClick ( id ) ;
202223 }
203224 } }
204225 />
@@ -239,7 +260,38 @@ export function DepositOverview() {
239260 onSuccess : refetchActivities ,
240261 } ) ;
241262
263+ // Manage broadcast modal state
264+ const [ broadcastingActivity , setBroadcastingActivity ] =
265+ useState < VaultActivity | null > ( null ) ;
266+ const [ broadcastSuccessOpen , setBroadcastSuccessOpen ] = useState ( false ) ;
267+
268+ // Broadcast modal handlers
269+ const handleBroadcastClick = useCallback (
270+ ( depositId : string ) => {
271+ const activity = allActivities . find ( ( a ) => a . id === depositId ) ;
272+ if ( activity ) {
273+ setBroadcastingActivity ( activity ) ;
274+ }
275+ } ,
276+ [ allActivities ] ,
277+ ) ;
278+
279+ const handleBroadcastClose = useCallback ( ( ) => {
280+ setBroadcastingActivity ( null ) ;
281+ } , [ ] ) ;
282+
283+ const handleBroadcastSuccess = useCallback ( ( ) => {
284+ setBroadcastingActivity ( null ) ;
285+ setBroadcastSuccessOpen ( true ) ;
286+ refetchActivities ( ) ; // Trigger refetch to update status
287+ } , [ refetchActivities ] ) ;
288+
289+ const handleBroadcastSuccessClose = useCallback ( ( ) => {
290+ setBroadcastSuccessOpen ( false ) ;
291+ } , [ ] ) ;
292+
242293 const { goToStep : goToDepositStep } = useVaultDepositState ( ) ;
294+ const { goToStep : goToRedeemStep } = useVaultRedeemState ( ) ;
243295
244296 const handleDeposit = ( ) => {
245297 if ( ! isConnected ) {
@@ -251,6 +303,12 @@ export function DepositOverview() {
251303 }
252304 } ;
253305
306+ const handleRedeem = ( ) => {
307+ if ( isConnected ) {
308+ goToRedeemStep ( VaultRedeemStep . FORM ) ;
309+ }
310+ } ;
311+
254312 // Transform VaultActivity to Deposit format for table
255313 const deposits : Deposit [ ] = useMemo ( ( ) => {
256314 return allActivities . map ( ( activity : VaultActivity ) => {
@@ -264,7 +322,7 @@ export function DepositOverview() {
264322 name : activity . providers [ 0 ] ?. name || "Unknown Provider" ,
265323 icon : activity . providers [ 0 ] ?. icon || "" ,
266324 } ,
267- status : state . displayLabel as "Available" | "Pending" | "In Use" ,
325+ status : state . displayLabel ,
268326 } ;
269327 } ) ;
270328 } , [ allActivities ] ) ;
@@ -333,6 +391,7 @@ export function DepositOverview() {
333391 btcPublicKey = { btcPublicKey }
334392 pendingPegins = { pendingPegins }
335393 onSignClick = { handleSignClick }
394+ onBroadcastClick = { handleBroadcastClick }
336395 />
337396 ) ;
338397 } ,
@@ -341,7 +400,7 @@ export function DepositOverview() {
341400
342401 return (
343402 < div className = "relative" >
344- { /* Header with Deposit button */ }
403+ { /* Header with Deposit and Redeem buttons */ }
345404 < div className = "mb-4 flex items-center justify-end gap-2" >
346405 < Button
347406 variant = "outlined"
@@ -352,6 +411,16 @@ export function DepositOverview() {
352411 >
353412 { isConnected ? "Deposit" : "Connect Wallet" }
354413 </ Button >
414+ < Button
415+ variant = "outlined"
416+ size = "medium"
417+ rounded
418+ onClick = { handleRedeem }
419+ aria-label = "Redeem BTC"
420+ disabled = { ! isConnected }
421+ >
422+ Redeem
423+ </ Button >
355424 </ div >
356425
357426 { /* Desktop: Deposits Table, Mobile: Deposit Cards */ }
@@ -367,6 +436,7 @@ export function DepositOverview() {
367436 btcPublicKey = { btcPublicKey }
368437 pendingPegins = { pendingPegins }
369438 onSignClick = { handleSignClick }
439+ onBroadcastClick = { handleBroadcastClick }
370440 />
371441 ) ;
372442 } ) }
@@ -389,6 +459,24 @@ export function DepositOverview() {
389459 onSuccess = { handlePayoutSignSuccess }
390460 />
391461 ) }
462+
463+ { /* Broadcast Sign Modal - Opens when clicking Sign & Broadcast button */ }
464+ { broadcastingActivity && ethAddress && (
465+ < BroadcastSignModal
466+ open = { ! ! broadcastingActivity }
467+ onClose = { handleBroadcastClose }
468+ activity = { broadcastingActivity }
469+ depositorEthAddress = { ethAddress }
470+ onSuccess = { handleBroadcastSuccess }
471+ />
472+ ) }
473+
474+ { /* Broadcast Success Modal - Shows after successful broadcast */ }
475+ < BroadcastSuccessModal
476+ open = { broadcastSuccessOpen }
477+ onClose = { handleBroadcastSuccessClose }
478+ amount = { broadcastingActivity ?. collateral . amount || "0" }
479+ />
392480 </ div >
393481 ) ;
394482}
0 commit comments