Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support set start block number for multisig address #3176

Merged
merged 2 commits into from
Jun 4, 2024
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
2 changes: 1 addition & 1 deletion packages/neuron-ui/src/components/AmendSUDTSend/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ const AmendSUDTSend = () => {
</div>
<div className={styles.rightFooter}>
<div className={styles.actions}>
<Button type="submit" disabled={disabled} label={t('send.send')}>
<Button type="submit" disabled={!!disabled} label={t('send.send')}>
{sending ? <Spinner /> : (t('send.submit-transaction') as string)}
</Button>
</div>
Expand Down
2 changes: 1 addition & 1 deletion packages/neuron-ui/src/components/AmendSend/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ const AmendSend = () => {
<span>{t('send.allow-use-sent-cell')}</span>
</label>
<div className={styles.actions}>
<Button type="submit" disabled={disabled} label={t('send.send')}>
<Button type="submit" disabled={!!disabled} label={t('send.send')}>
{sending ? <Spinner /> : (t('send.submit-transaction') as string)}
</Button>
</div>
Expand Down
80 changes: 72 additions & 8 deletions packages/neuron-ui/src/components/MultisigAddress/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,21 @@ export const useConfigManage = ({ walletId, isMainnet }: { walletId: string; isM
}
})
}, [setEntities])
const updateConfig = useCallback(
const onUpdateConfig = useCallback((values: Partial<MultisigEntity> & { id: number }) => {
return updateMultisigConfig(values).then(res => {
if (isSuccessResponse(res)) {
setEntities(v => v.map(config => (res.result && config.id === res.result?.id ? res.result : config)))
} else {
throw new Error(typeof res.message === 'string' ? res.message : res.message.content!)
}
})
}, [])
const onUpdateConfigAlias = useCallback(
(id: number) => (e: React.SyntheticEvent<unknown>) => {
const { value } = e.target as HTMLInputElement
updateMultisigConfig({ id, alias: value || '' }).then(res => {
if (isSuccessResponse(res)) {
setEntities(v => v.map(config => (res.result && config.id === res.result?.id ? res.result : config)))
}
})
onUpdateConfig({ id, alias: value || '' })
},
[setEntities]
[onUpdateConfig]
)
const deleteConfigById = useCallback(
(id: number) => {
Expand Down Expand Up @@ -141,7 +146,8 @@ export const useConfigManage = ({ walletId, isMainnet }: { walletId: string; isM
return {
saveConfig,
allConfigs,
updateConfig,
onUpdateConfigAlias,
onUpdateConfig,
deleteConfigById,
onImportConfig,
configs,
Expand Down Expand Up @@ -365,3 +371,61 @@ export const useSubscription = ({
}, [isLightClient, getAndSaveMultisigSyncProgress])
return { multisigBanlances, multisigSyncProgress }
}

export const useCancelWithLightClient = () => {
const [isCloseWarningDialogShow, setIsCloseWarningDialogShow] = useState(false)
const onCancel = useCallback(() => {
setIsCloseWarningDialogShow(true)
}, [setIsCloseWarningDialogShow])
const onCancelCloseMultisigDialog = useCallback(() => {
setIsCloseWarningDialogShow(false)
}, [setIsCloseWarningDialogShow])
return {
isCloseWarningDialogShow,
onCancel,
onCancelCloseMultisigDialog,
}
}

export const useSetStartBlockNumber = ({
onUpdateConfig,
}: {
onUpdateConfig: (v: Partial<MultisigEntity> & { id: number }) => Promise<void>
}) => {
const [isSetStartBlockShown, setIsSetStartBlockShown] = useState(false)
const [editId, setEditId] = useState<number | undefined>()
const [address, setAddress] = useState<string | undefined>()
const [lastStartBlockNumber, setLastStartBlockNumber] = useState<number | undefined>()
const onConfirm = useCallback(
(startBlockNumber: number) => {
if (editId) {
return onUpdateConfig({
id: editId,
startBlockNumber,
}).then(() => {
setIsSetStartBlockShown(false)
})
}
return Promise.reject(new Error('The Edit multisig config is empty'))
},
[editId]
)
const openDialog = useCallback<React.MouseEventHandler<HTMLButtonElement>>(e => {
yanguoyu marked this conversation as resolved.
Show resolved Hide resolved
const { id, address: editAddress, startBlockNumber } = e.currentTarget.dataset
if (id) {
setEditId(+id)
}
setAddress(editAddress)
setLastStartBlockNumber(startBlockNumber ? +startBlockNumber : undefined)
setIsSetStartBlockShown(true)
}, [])
return {
openDialog,
closeDialog: useCallback(() => setIsSetStartBlockShown(false), []),
isSetStartBlockShown,
onConfirm,
address,
lastStartBlockNumber,
onCancel: useCallback(() => setIsSetStartBlockShown(false), []),
}
}
140 changes: 119 additions & 21 deletions packages/neuron-ui/src/components/MultisigAddress/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback, useMemo, useState } from 'react'
import React, { useCallback, useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import {
useOnLocaleChange,
Expand All @@ -11,24 +11,39 @@ import { useState as useGlobalState } from 'states'
import MultisigAddressCreateDialog from 'components/MultisigAddressCreateDialog'
import MultisigAddressInfo from 'components/MultisigAddressInfo'
import SendFromMultisigDialog from 'components/SendFromMultisigDialog'
import { MultisigConfig } from 'services/remote'
import { MultisigConfig, changeMultisigSyncStatus } from 'services/remote'
import ApproveMultisigTxDialog from 'components/ApproveMultisigTxDialog'
import Dialog from 'widgets/Dialog'
import Table from 'widgets/Table'
import Tooltip from 'widgets/Tooltip'
import AlertDialog from 'widgets/AlertDialog'
import { ReactComponent as AddSimple } from 'widgets/Icons/AddSimple.svg'
import { ReactComponent as Details } from 'widgets/Icons/Details.svg'
import { ReactComponent as Delete } from 'widgets/Icons/Delete.svg'
import { ReactComponent as Confirm } from 'widgets/Icons/Confirm.svg'
import { ReactComponent as Transfer } from 'widgets/Icons/Transfer.svg'
import { ReactComponent as Upload } from 'widgets/Icons/Upload.svg'
import { ReactComponent as Edit } from 'widgets/Icons/Edit.svg'
import { Download, Search } from 'widgets/Icons/icon'
import {
Download,
Search,
AddSimple,
Details,
Delete,
Confirm,
Transfer,
Upload,
Edit,
Confirming,
} from 'widgets/Icons/icon'
import AttentionCloseDialog from 'widgets/Icons/Attention.png'
import { HIDE_BALANCE, NetworkType } from 'utils/const'
import { onEnter } from 'utils/inputDevice'
import getMultisigSignStatus from 'utils/getMultisigSignStatus'
import { useSearch, useConfigManage, useExportConfig, useActions, useSubscription } from './hooks'
import Button from 'widgets/Button'
import SetStartBlockNumberDialog from 'components/SetStartBlockNumberDialog'
import {
useSearch,
useConfigManage,
useExportConfig,
useActions,
useSubscription,
useCancelWithLightClient,
useSetStartBlockNumber,
} from './hooks'

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

Expand Down Expand Up @@ -58,7 +73,11 @@ const MultisigAddress = () => {
useExitOnWalletChange()
const {
wallet: { id: walletId, addresses },
chain: { networkID },
chain: {
syncState: { bestKnownBlockNumber },
networkID,
connectionStatus,
},
settings: { networks = [] },
} = useGlobalState()
const isMainnet = isMainnetUtil(networks, networkID)
Expand All @@ -67,11 +86,19 @@ const MultisigAddress = () => {
[networks, networkID]
)
const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false)
const { allConfigs, saveConfig, updateConfig, deleteConfigById, onImportConfig, configs, onFilterConfig } =
useConfigManage({
walletId,
isMainnet,
})
const {
allConfigs,
saveConfig,
onUpdateConfig,
onUpdateConfigAlias,
deleteConfigById,
onImportConfig,
configs,
onFilterConfig,
} = useConfigManage({
walletId,
isMainnet,
})
const { multisigBanlances, multisigSyncProgress } = useSubscription({
walletId,
isMainnet,
Expand Down Expand Up @@ -141,10 +168,39 @@ const MultisigAddress = () => {
}, [multisigBanlances, sendAction.sendFromMultisig])

const onBack = useGoBack()
const {
onCancel: onCancelWithLight,
isCloseWarningDialogShow,
onCancelCloseMultisigDialog,
} = useCancelWithLightClient()
const {
isSetStartBlockShown,
openDialog: openSetStartBlockNumber,
lastStartBlockNumber,
address,
onConfirm,
onCancel,
} = useSetStartBlockNumber({ onUpdateConfig })

useEffect(() => {
if (isLightClient) {
changeMultisigSyncStatus(true)
}
return () => {
if (isLightClient) {
changeMultisigSyncStatus(false)
}
}
}, [isLightClient])

return (
<div>
<Dialog show={showMainDialog} title={t('multisig-address.window-title')} onCancel={onBack} showFooter={false}>
<Dialog
show={showMainDialog}
title={t('multisig-address.window-title')}
onCancel={isLightClient ? onCancelWithLight : onBack}
showFooter={false}
>
<div className={styles.container}>
<div className={styles.head}>
<div className={styles.searchBox}>
Expand Down Expand Up @@ -221,8 +277,8 @@ const MultisigAddress = () => {
<textarea
className={styles.descInput}
value={item.alias || ''}
onChange={updateConfig(item.id)}
onKeyDown={updateConfig(item.id)}
onChange={onUpdateConfigAlias(item.id)}
onKeyDown={onUpdateConfigAlias(item.id)}
/>
<Edit />
</div>
Expand Down Expand Up @@ -261,7 +317,21 @@ const MultisigAddress = () => {
align: 'left',
hidden: !isLightClient,
render(_, __, item) {
return <div>{multisigSyncProgress?.[item.fullPayload] ?? 0}</div>
return (
<div className={styles.syncBlock}>
{connectionStatus === 'online' ? <Confirming className={styles.syncing} /> : null}
{multisigSyncProgress?.[item.fullPayload] ?? 0}
<Button
type="text"
onClick={openSetStartBlockNumber}
data-id={item.id}
data-address={item.fullPayload}
data-start-block-number={item.startBlockNumber}
>
<Edit />
</Button>
</div>
)
},
},
{
Expand Down Expand Up @@ -366,6 +436,23 @@ const MultisigAddress = () => {
}}
/>

<Dialog
title={t('multisig-address.multi-details')}
show={isCloseWarningDialogShow}
onConfirm={onBack}
onCancel={onCancelCloseMultisigDialog}
confirmText={t('multisig-address.ok')}
contentClassName={styles.closeMutisigContent}
className={styles.closeMultisigDialog}
confirmProps={{ type: 'cancel', className: styles.confirmBtn }}
>
<img src={AttentionCloseDialog} alt="Synchronization Abort" />
<h4>Synchronization Abort</h4>
<p>
Leaving the current window will cause the multisig synchronization to be aborted, so please confirm to leave.
</p>
</Dialog>

{sendAction.sendFromMultisig && sendAction.isDialogOpen ? (
<SendFromMultisigDialog
closeDialog={sendAction.closeDialog}
Expand All @@ -382,6 +469,17 @@ const MultisigAddress = () => {
isMainnet={isMainnet}
/>
) : null}
{address ? (
<SetStartBlockNumberDialog
show={isSetStartBlockShown}
headerTipNumber={bestKnownBlockNumber}
initStartBlockNumber={lastStartBlockNumber}
isMainnet={isMainnet}
address={address}
onUpdateStartBlockNumber={onConfirm}
onCancel={onCancel}
/>
) : null}
</div>
)
}
Expand Down
Loading