Skip to content

Commit

Permalink
feat: Support set start block number for multisig address (#3176)
Browse files Browse the repository at this point in the history
* feat: Support set start block number for multisig address

* fix: Add pause status for wallet sync
  • Loading branch information
yanguoyu authored Jun 4, 2024
1 parent 5d4afb1 commit 29ba444
Show file tree
Hide file tree
Showing 47 changed files with 714 additions and 365 deletions.
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 => {
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

2 comments on commit 29ba444

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Packaging for test is done in 9366864013

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Packaging for test is done in 9366862196

Please sign in to comment.