@@ -4,9 +4,20 @@ import { useState as useGlobalState } from 'states'
44import { sudtValueToAmount , shannonToCKBFormatter } from 'utils/formatters'
55import Dialog from 'widgets/Dialog'
66import AlertDialog from 'widgets/AlertDialog'
7+ import Button from 'widgets/Button'
78import TextField from 'widgets/TextField'
89import { isErrorWithI18n } from 'exceptions'
9- import { getUDTTokenInfoAndBalance , generateRecycleUDTCellTx , openExternal , sendTx } from 'services/remote'
10+ import Hardware from 'widgets/Icons/Hardware.png'
11+ import Alert from 'widgets/Alert'
12+ import { useHardWallet , usePassword } from 'components/CellManagement/hooks'
13+ import {
14+ getUDTTokenInfoAndBalance ,
15+ generateRecycleUDTCellTx ,
16+ openExternal ,
17+ signAndBroadcastTransaction ,
18+ OfflineSignStatus ,
19+ OfflineSignType ,
20+ } from 'services/remote'
1021import {
1122 UDTType ,
1223 addressToScript ,
@@ -24,7 +35,7 @@ export interface DataProps {
2435 udtType : UDTType
2536}
2637
27- type DialogType = 'ready' | 'inProgress' | 'success'
38+ type DialogType = 'ready' | 'inProgress' | 'verify' | ' success'
2839
2940const RecycleUDTCellDialog = ( {
3041 data,
@@ -36,19 +47,30 @@ const RecycleUDTCellDialog = ({
3647 onConfirm ?: ( ) => void
3748} ) => {
3849 const {
39- wallet : { id : walletID = '' , addresses } ,
50+ wallet,
4051 settings : { networks } ,
4152 chain : { networkID } ,
4253 } = useGlobalState ( )
4354 const [ t ] = useTranslation ( )
44- const [ password , setPassword ] = useState ( '' )
45- const [ passwordError , setPasswordError ] = useState ( '' )
4655 const [ receiver , setReceiver ] = useState ( '' )
4756 const [ isCurrentWallet , setIsCurrentWallet ] = useState ( false )
4857 const [ isLoading , setIsLoading ] = useState ( false )
4958 const [ dialogType , setDialogType ] = useState < DialogType > ( 'ready' )
5059 const [ txHash , setTxHash ] = useState ( '' )
5160 const [ info , setInfo ] = useState < Controller . GetUDTTokenInfoAndBalance . Response | null > ( null )
61+ const { id : walletID = '' , addresses, device } = wallet
62+ const { password, error, onPasswordChange, setError } = usePassword ( )
63+ const {
64+ isReconnecting,
65+ isNotAvailable,
66+ reconnect,
67+ verifyDeviceStatus,
68+ errorMessage : hardwalletError ,
69+ setError : setHardwalletError ,
70+ } = useHardWallet ( {
71+ wallet,
72+ t,
73+ } )
5274
5375 const { address : holder , tokenID, udtType } = data
5476
@@ -80,15 +102,6 @@ const RecycleUDTCellDialog = ({
80102 } )
81103 } , [ ] )
82104
83- const onPasswordChange = useCallback (
84- ( e : React . SyntheticEvent < HTMLInputElement > ) => {
85- const { value } = e . target as HTMLInputElement
86- setPassword ( value )
87- setPasswordError ( '' )
88- } ,
89- [ setPassword , setPasswordError ]
90- )
91-
92105 const onAddressChange = useCallback (
93106 ( e : React . SyntheticEvent < HTMLInputElement > ) => {
94107 const { value } = e . target as HTMLInputElement
@@ -119,45 +132,53 @@ const RecycleUDTCellDialog = ({
119132 openExternal ( `${ explorerUrl } /transaction/${ txHash } ` )
120133 } , [ isMainnet , txHash ] )
121134
135+ const handleVerify = useCallback ( async ( ) => {
136+ await verifyDeviceStatus ( )
137+ setDialogType ( 'verify' )
138+ } , [ setDialogType ] )
139+
122140 const onSubmit = useCallback (
123- ( e ?: React . FormEvent ) => {
141+ async ( e ?: React . FormEvent ) => {
124142 if ( e ) {
125143 e . preventDefault ( )
126144 }
127- if ( ! password ) {
128- return
129- }
130145 setIsLoading ( true )
131- generateRecycleUDTCellTx ( {
146+
147+ const errFunc = wallet . device ? setHardwalletError : setError
148+
149+ const txRes = await generateRecycleUDTCellTx ( {
132150 walletId : walletID ,
133151 tokenID,
134152 holder,
135153 receiver : addressToScript ( receiver , { isMainnet } ) . args ,
136154 udtType,
137- } ) . then ( txRes => {
138- if ( ! isSuccessResponse ( txRes ) ) {
139- setPasswordError ( errorFormatter ( txRes . message , t ) )
140- setIsLoading ( false )
141- return
142- }
143- sendTx ( {
144- walletID,
145- tx : txRes . result ,
146- password,
147- } ) . then ( res => {
148- if ( ! isSuccessResponse ( res ) ) {
149- setPasswordError ( errorFormatter ( res . message , t ) )
150- setIsLoading ( false )
151- return
152- }
153- setIsLoading ( false )
154- onConfirm ?.( )
155- setTxHash ( res . result )
156- setDialogType ( 'success' )
157- } )
158155 } )
156+ if ( ! isSuccessResponse ( txRes ) ) {
157+ errFunc ( errorFormatter ( txRes . message , t ) )
158+ setIsLoading ( false )
159+ return
160+ }
161+ const tx = txRes . result
162+
163+ const res = await signAndBroadcastTransaction ( {
164+ transaction : tx ,
165+ status : OfflineSignStatus . Unsigned ,
166+ type : OfflineSignType . Regular ,
167+ walletID,
168+ password,
169+ } )
170+ if ( ! isSuccessResponse ( res ) ) {
171+ errFunc ( errorFormatter ( res . message , t ) )
172+ setIsLoading ( false )
173+ return
174+ }
175+
176+ setIsLoading ( false )
177+ setTxHash ( res . result )
178+ onConfirm ?.( )
179+ setDialogType ( 'success' )
159180 } ,
160- [ walletID , password , setPasswordError , setTxHash , holder , t ]
181+ [ walletID , password , setError , setTxHash , holder , t , receiver ]
161182 )
162183
163184 if ( dialogType === 'ready' || ! info ) {
@@ -189,15 +210,44 @@ const RecycleUDTCellDialog = ({
189210 )
190211 }
191212
213+ if ( dialogType === 'verify' ) {
214+ return (
215+ < Dialog
216+ show
217+ title = { t ( 's-udt.recycle-dialog.title' ) }
218+ onCancel = { onClose }
219+ showFooter = { false }
220+ className = { styles . verifyDialog }
221+ >
222+ < div >
223+ < img src = { Hardware } alt = "hard-wallet" className = { styles . hardWalletImg } />
224+ </ div >
225+ < div className = { styles . lockActions } >
226+ < Button onClick = { onClose } type = "cancel" >
227+ { t ( 'common.cancel' ) }
228+ </ Button >
229+ < Button onClick = { isNotAvailable ? reconnect : onSubmit } loading = { isLoading || isReconnecting } type = "primary" >
230+ { isNotAvailable || isReconnecting ? t ( 's-udt.recycle-dialog.connect-wallet' ) : t ( 'cell-manage.verify' ) }
231+ </ Button >
232+ </ div >
233+ { hardwalletError ? (
234+ < Alert status = "error" className = { styles . hardwalletErr } >
235+ { hardwalletError }
236+ </ Alert >
237+ ) : null }
238+ </ Dialog >
239+ )
240+ }
241+
192242 return (
193243 < Dialog
194244 show
195245 title = { t ( 's-udt.recycle-dialog.title' ) }
196246 onCancel = { onClose }
197- onConfirm = { onSubmit }
247+ onConfirm = { device ? handleVerify : onSubmit }
198248 confirmText = { t ( 'wizard.next' ) }
199249 isLoading = { isLoading }
200- disabled = { ! password || ! receiver || ! ! receiveAddressError || isLoading }
250+ disabled = { ( ! password && ! device ) || ! receiver || ! ! receiveAddressError }
201251 className = { styles . dialog }
202252 >
203253 < div >
@@ -228,18 +278,20 @@ const RecycleUDTCellDialog = ({
228278 />
229279 </ div >
230280
231- < TextField
232- className = { styles . inputField }
233- placeholder = { t ( 'password-request.placeholder' ) }
234- width = "100%"
235- label = { t ( 'wizard.password' ) }
236- value = { password }
237- field = "password"
238- type = "password"
239- onChange = { onPasswordChange }
240- autoFocus
241- error = { passwordError }
242- />
281+ { ! device && (
282+ < TextField
283+ className = { styles . inputField }
284+ placeholder = { t ( 'password-request.placeholder' ) }
285+ width = "100%"
286+ label = { t ( 'wizard.password' ) }
287+ value = { password }
288+ field = "password"
289+ type = "password"
290+ onChange = { onPasswordChange }
291+ autoFocus
292+ error = { error }
293+ />
294+ ) }
243295 </ div >
244296 </ Dialog >
245297 )
0 commit comments