Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Comment thread
devchenyan marked this conversation as resolved.
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