Skip to content

Commit

Permalink
fix: Hot/cold combination of a wallet doesn't work smooth (nervosnetw…
Browse files Browse the repository at this point in the history
…ork#3000)

* fix: issue 288

* fix: broadcastTransaction

* fix: BroadcastTransaction

* fix: French

* fix: broadcastTransactionOnly

* fix: comments

* fix: broadcastSignedTransaction

* fix

* feat: remove Wallet field

---------

Co-authored-by: Chen Yu <[email protected]>
  • Loading branch information
2 people authored and yanguoyu committed Mar 14, 2024
1 parent 3b1ee7c commit 4783ffb
Show file tree
Hide file tree
Showing 20 changed files with 359 additions and 119 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
.main {
tr {
td {
font-size: 14px;
line-height: 26px;
color: var(--main-text-color);
svg {
width: 14px;
height: 14px;
margin-right: 4px;
position: relative;
top: 2px;
}
}
.first {
padding-right: 24px;
color: var(--input-second-color);
}
}
}

.warningDialog {
width: 680px;
.content {
display: flex;
justify-content: center;
margin-top: 24px;
color: var(--main-text-color);
}
}

.textarea {
color: var(--main-text-color);
margin-top: 17px;
width: 648px;
height: 206px;
resize: none;
background: var(--secondary-background-color);
border: 1px solid var(--divide-line-color);
border-radius: 8px;
padding: 16px;
}
136 changes: 136 additions & 0 deletions packages/neuron-ui/src/components/BroadcastTransaction/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import React, { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useNavigate } from 'react-router-dom'
import { isSuccessResponse, RoutePath, isMainnet as isMainnetUtil, useGoBack, getExplorerUrl } from 'utils'
import Dialog from 'widgets/Dialog'
import AlertDialog from 'widgets/AlertDialog'
import { useDispatch, useState as useGlobalState } from 'states'
import { broadcastSignedTransaction, OfflineSignStatus, openExternal, getTransactionList } from 'services/remote'

import styles from './broadcastTransaction.module.scss'

const BroadcastTransaction = () => {
const {
app: { loadedTransaction = {} },
chain: { networkID },
settings: { networks },
wallet,
} = useGlobalState()

const [isBroadcasting, setIsBroadcasting] = useState(false)
const [broadcastedTxHash, setBroadcastedTxHash] = useState<string | null>('')
const [t] = useTranslation()
const dispatch = useDispatch()
const [errMsg, setErrMsg] = useState('')
const isMainnet = isMainnetUtil(networks, networkID)

const { filePath, json } = loadedTransaction

const jsonContent = useMemo(() => {
return JSON.stringify(json, null, 2)
}, [json])

const signStatus: OfflineSignStatus = json.status

const isSigned = useMemo(() => signStatus === OfflineSignStatus.Signed, [signStatus])

const onBack = useGoBack()

const navigate = useNavigate()
const onBroadcast = useCallback(async () => {
if (broadcastedTxHash) {
openExternal(`${getExplorerUrl(isMainnet)}/transaction/${broadcastedTxHash}`)
return
}

setIsBroadcasting(true)

const res = await broadcastSignedTransaction({
...json,
})

setIsBroadcasting(false)

if (isSuccessResponse(res)) {
if (!wallet?.id) {
setBroadcastedTxHash(res.result)
return
}

if (res.result) {
getTransactionList({
walletID: wallet.id,
pageNo: 1,
pageSize: 10,
keywords: res.result,
}).then(txRes => {
if (isSuccessResponse(txRes) && txRes.result.items.length) {
navigate(RoutePath.History)
} else {
setBroadcastedTxHash(res.result)
}
})
}
} else {
setErrMsg(typeof res.message === 'string' ? res.message : res.message.content || '')
}
}, [wallet, json, navigate, dispatch, broadcastedTxHash, setBroadcastedTxHash])

return (
<>
<Dialog
show={isSigned}
title={t('offline-sign.broadcast-transaction')}
cancelText={t('offline-sign.actions.cancel')}
onCancel={onBack}
confirmText={
broadcastedTxHash ? t('offline-sign.actions.view-in-explorer') : t('offline-sign.actions.broadcast')
}
isLoading={isBroadcasting}
onConfirm={onBroadcast}
>
<div className={styles.main}>
<table>
<tbody>
<tr>
<td className={styles.first}>{t('offline-sign.json-file')}</td>
<td>{filePath}</td>
</tr>
<tr>
<td className={styles.first}>{t('offline-sign.status.label')}</td>
<td>{t('offline-sign.status.signed')}</td>
</tr>
<tr>
<td className={styles.first}>{t('offline-sign.content')}</td>
</tr>
</tbody>
</table>
<textarea disabled value={jsonContent} className={styles.textarea} />
</div>
</Dialog>

<Dialog
show={!isSigned}
className={styles.warningDialog}
title={t('offline-sign.import-transaction-to-sign')}
cancelText={t('offline-sign.actions.cancel')}
onCancel={onBack}
onConfirm={onBack}
>
<div className={styles.content}>{t('offline-sign.import-unsigned-transaction-detail')}</div>
</Dialog>

<AlertDialog
show={!!errMsg}
title={t('message-types.alert')}
message={errMsg}
type="failed"
onCancel={() => setErrMsg('')}
/>
</>
)
}

BroadcastTransaction.displayName = 'BroadcastTransaction'

export default BroadcastTransaction
60 changes: 28 additions & 32 deletions packages/neuron-ui/src/components/OfflineSign/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import React, { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useNavigate } from 'react-router-dom'
import { isSuccessResponse, RoutePath, useDidMount, useGoBack } from 'utils'
import { isSuccessResponse, useDidMount, useGoBack } from 'utils'
import Dialog from 'widgets/Dialog'
import AlertDialog from 'widgets/AlertDialog'
import { useDispatch, useState as useGlobalState } from 'states'
import { broadcastTransaction, getCurrentWallet, OfflineSignStatus } from 'services/remote'
import { useState as useGlobalState } from 'states'
import { getCurrentWallet, OfflineSignStatus } from 'services/remote'
import { ReactComponent as HardWalletIcon } from 'widgets/Icons/HardWallet.svg'
import OfflineSignDialog from '../OfflineSignDialog'

Expand All @@ -18,9 +17,7 @@ const OfflineSign = () => {

const [wallet, setWallet] = useState<State.Wallet | null>(null)
const [isSigning, setIsSigning] = useState(false)
const [isBroadCasting, setIsBroadcasting] = useState(false)
const [t] = useTranslation()
const dispatch = useDispatch()
const [errMsg, setErrMsg] = useState('')

const { filePath, json } = loadedTransaction
Expand All @@ -31,6 +28,8 @@ const OfflineSign = () => {

const signStatus: OfflineSignStatus = json.status

const isSigned = useMemo(() => signStatus === OfflineSignStatus.Signed, [signStatus])

const status = useMemo(() => {
switch (signStatus) {
case OfflineSignStatus.Unsigned:
Expand All @@ -48,24 +47,6 @@ const OfflineSign = () => {
setIsSigning(true)
}, [setIsSigning])

const navigate = useNavigate()
const onBroadcast = useCallback(async () => {
setIsBroadcasting(true)
try {
const res = await broadcastTransaction({
...json,
walletID: wallet!.id,
})
if (isSuccessResponse(res)) {
navigate(RoutePath.History)
} else {
setErrMsg(typeof res.message === 'string' ? res.message : res.message.content || '')
}
} finally {
setIsBroadcasting(false)
}
}, [wallet, json, navigate, dispatch])

useDidMount(() => {
getCurrentWallet().then(res => {
if (isSuccessResponse(res)) {
Expand All @@ -76,26 +57,29 @@ const OfflineSign = () => {

const signDialogOnDismiss = useCallback(() => {
setIsSigning(false)
}, [])
}, [setIsSigning])

if (isSigning && wallet) {
return (
<OfflineSignDialog isBroadcast={false} wallet={wallet} offlineSignJSON={json} onDismiss={signDialogOnDismiss} />
<OfflineSignDialog
isBroadcast={false}
wallet={wallet}
offlineSignJSON={json}
onDismiss={signDialogOnDismiss}
onCompleted={onBack}
/>
)
}

return (
<>
<Dialog
show={!isSigning}
show={!isSigned}
title={t('offline-sign.title')}
cancelText={t('offline-sign.actions.cancel')}
onCancel={onBack}
confirmText={
signStatus === OfflineSignStatus.Signed ? t('offline-sign.actions.broadcast') : t('offline-sign.actions.sign')
}
isLoading={signStatus === OfflineSignStatus.Signed && isBroadCasting}
onConfirm={signStatus === OfflineSignStatus.Signed ? onBroadcast : onSign}
confirmText={t('offline-sign.actions.sign')}
onConfirm={onSign}
>
<div className={styles.main}>
<table>
Expand Down Expand Up @@ -123,6 +107,18 @@ const OfflineSign = () => {
<textarea disabled value={jsonContent} className={styles.textarea} />
</div>
</Dialog>

<Dialog
show={isSigned}
className={styles.warningDialog}
title={t('offline-sign.import-signed-transaction')}
cancelText={t('offline-sign.actions.cancel')}
onCancel={onBack}
onConfirm={onBack}
>
<div className={styles.content}>{t('offline-sign.import-signed-transaction-detail')}</div>
</Dialog>

<AlertDialog
show={!!errMsg}
title={t('message-types.alert')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@
}
}

.warningDialog {
width: 680px;
.content {
display: flex;
justify-content: center;
margin-top: 24px;
color: var(--main-text-color);
}
}

.textarea {
color: var(--main-text-color);
margin-top: 17px;
Expand Down
7 changes: 4 additions & 3 deletions packages/neuron-ui/src/components/OfflineSignDialog/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ interface SignDialogProps {
wallet: State.Wallet
offlineSignJSON: OfflineSignJSON
onDismiss: () => void
onCompleted: () => void
}

const OfflineSignDialog = ({ isBroadcast, wallet, offlineSignJSON, onDismiss }: SignDialogProps) => {
const OfflineSignDialog = ({ isBroadcast, wallet, offlineSignJSON, onDismiss, onCompleted }: SignDialogProps) => {
const {
app: {
send: { description },
Expand Down Expand Up @@ -65,8 +66,8 @@ const OfflineSignDialog = ({ isBroadcast, wallet, offlineSignJSON, onDismiss }:
type: AppActions.UpdateLoadedTransaction,
payload: res.result!,
})
onDismiss()
}, [offlineSignJSON, dispatch, onDismiss, t, password, walletID])
onCompleted()
}, [offlineSignJSON, dispatch, onCompleted, t, password, walletID])

const onSubmit = useCallback(
async (e?: React.FormEvent) => {
Expand Down
10 changes: 8 additions & 2 deletions packages/neuron-ui/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@
"partially-signed": "Partially Signed",
"signed": "Signed"
},
"import-signed-transaction": "Import a signed transaction",
"import-signed-transaction-detail": "You have imported a signed transaction, please confirm and try again.",
"wallet": "Wallet:",
"content": "Content:",
"export": "Export Tx",
Expand All @@ -122,8 +124,12 @@
"actions": {
"broadcast": "Broadcast",
"sign": "Sign and export",
"cancel": "Cancel"
}
"cancel": "Cancel",
"view-in-explorer": "View in Explorer"
},
"broadcast-transaction": "Broadcast Transaction",
"import-transaction-to-sign": "Import a transaction to sign",
"import-unsigned-transaction-detail": "You have imported an unsigned transaction, please confirm and try again."
},
"overview": {
"date": "Date",
Expand Down
Loading

0 comments on commit 4783ffb

Please sign in to comment.