Skip to content

Commit 95823eb

Browse files
authored
feat: Manage Nervos DAO with multisig address (nervosnetwork#3298)
* feat: Manage Nervos DAO with multisig address * update * update * fix: comments * fix: comments * fix: comments * fix: check * fix * fix * fix
1 parent 1f692b9 commit 95823eb

File tree

29 files changed

+1420
-99
lines changed

29 files changed

+1420
-99
lines changed

packages/neuron-ui/src/components/DepositDialog/hooks.ts

Lines changed: 69 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ import { TFunction } from 'i18next'
33
import { Dispatch, SetStateAction, useCallback, useEffect, useMemo, useRef, useState } from 'react'
44
import { useTranslation } from 'react-i18next'
55
import {
6+
MultisigConfig,
67
generateDaoDepositAllTx as generateDaoDepositAllTxAPI,
78
generateDaoDepositTx as generateDaoDepositTxAPI,
9+
generateMultisigDaoDepositTx as generateMultisigDaoDepositTxAPI,
10+
generateMultisigDaoDepositAllTx as generateMultisigDaoDepositAllTxAPI,
811
} from 'services/remote'
912
import { AppActions, useDispatch } from 'states'
1013
import {
@@ -17,6 +20,7 @@ import {
1720
useClearGeneratedTx,
1821
validateAmount,
1922
} from 'utils'
23+
import getMultisigSignStatus from 'utils/getMultisigSignStatus'
2024
import { MAX_DECIMAL_DIGITS, MIN_DEPOSIT_AMOUNT, SHANNON_CKB_RATIO } from 'utils/const'
2125

2226
const PERCENT_100 = 100
@@ -45,17 +49,26 @@ function generateDaoDepositTx({
4549
capacity,
4650
suggestFeeRate,
4751
t,
52+
multisigConfig,
4853
}: {
4954
walletID: string
5055
capacity: string
5156
suggestFeeRate: number
5257
t: TFunction
58+
multisigConfig?: MultisigConfig
5359
}): Promise<State.GeneratedTx | null> {
54-
return generateDaoDepositTxAPI({
55-
feeRate: `${suggestFeeRate}`,
56-
capacity,
57-
walletID,
58-
}).then(res => {
60+
const generateCall = multisigConfig
61+
? generateMultisigDaoDepositTxAPI({
62+
feeRate: `${suggestFeeRate}`,
63+
capacity,
64+
multisigConfig,
65+
})
66+
: generateDaoDepositTxAPI({
67+
walletID,
68+
feeRate: `${suggestFeeRate}`,
69+
capacity,
70+
})
71+
return generateCall.then(res => {
5972
if (isSuccessResponse(res)) {
6073
return res.result
6174
}
@@ -73,16 +86,25 @@ function generateDaoDepositAllTx({
7386
suggestFeeRate,
7487
isBalanceReserved,
7588
walletID,
89+
multisigConfig,
7690
}: {
7791
suggestFeeRate: number
7892
isBalanceReserved: boolean
7993
walletID: string
94+
multisigConfig?: MultisigConfig
8095
}): Promise<State.GeneratedTx | null> {
81-
return generateDaoDepositAllTxAPI({
82-
walletID,
83-
feeRate: `${suggestFeeRate}`,
84-
isBalanceReserved,
85-
}).then(res => {
96+
const generateAllCall = multisigConfig
97+
? generateMultisigDaoDepositAllTxAPI({
98+
feeRate: `${suggestFeeRate}`,
99+
isBalanceReserved,
100+
multisigConfig,
101+
})
102+
: generateDaoDepositAllTxAPI({
103+
walletID,
104+
feeRate: `${suggestFeeRate}`,
105+
isBalanceReserved,
106+
})
107+
return generateAllCall.then(res => {
86108
if (isSuccessResponse(res)) {
87109
return res.result
88110
}
@@ -97,13 +119,15 @@ export const useGenerateDaoDepositTx = ({
97119
suggestFeeRate,
98120
showDepositDialog,
99121
slidePercent,
122+
multisigConfig,
100123
}: {
101124
walletID: string
102125
isBalanceReserved: boolean
103126
depositValue: string
104127
suggestFeeRate: number
105128
showDepositDialog: boolean
106129
slidePercent: number
130+
multisigConfig?: MultisigConfig
107131
}) => {
108132
const timer = useRef<ReturnType<typeof setTimeout>>()
109133
const [errorMessage, setErrorMessage] = useState('')
@@ -127,8 +151,14 @@ export const useGenerateDaoDepositTx = ({
127151
}
128152

129153
const generateDaoDepositResult: Promise<State.GeneratedTx | null> = isDepositAll
130-
? generateDaoDepositAllTx({ walletID, isBalanceReserved, suggestFeeRate })
131-
: generateDaoDepositTx({ walletID, capacity: CKBToShannonFormatter(depositValue), suggestFeeRate, t })
154+
? generateDaoDepositAllTx({ walletID, isBalanceReserved, suggestFeeRate, multisigConfig })
155+
: generateDaoDepositTx({
156+
walletID,
157+
capacity: CKBToShannonFormatter(depositValue),
158+
suggestFeeRate,
159+
t,
160+
multisigConfig,
161+
})
132162
generateDaoDepositResult
133163
.then(res => {
134164
dispatch({
@@ -239,22 +269,38 @@ export const useBalanceReserved = () => {
239269

240270
export const useOnDepositDialogSubmit = ({
241271
onDepositSuccess,
242-
walletID,
272+
wallet,
273+
multisigConfig,
243274
}: {
244275
onDepositSuccess: () => void
245-
walletID: string
276+
wallet: State.Wallet
277+
multisigConfig?: MultisigConfig
246278
}) => {
247279
const dispatch = useDispatch()
248280
return useCallback(() => {
249-
dispatch({
250-
type: AppActions.RequestPassword,
251-
payload: {
252-
walletID,
253-
actionType: 'send',
254-
onSuccess: onDepositSuccess,
255-
},
256-
})
257-
}, [dispatch, walletID, onDepositSuccess])
281+
if (multisigConfig) {
282+
const { canBroadcastAfterSign } = getMultisigSignStatus({ multisigConfig, addresses: wallet.addresses })
283+
dispatch({
284+
type: AppActions.RequestPassword,
285+
payload: {
286+
walletID: wallet.id,
287+
actionType: canBroadcastAfterSign ? 'send-from-multisig-need-one' : 'send-from-multisig',
288+
multisigConfig,
289+
onSuccess: onDepositSuccess,
290+
title: 'password-request.verify-password',
291+
},
292+
})
293+
} else {
294+
dispatch({
295+
type: AppActions.RequestPassword,
296+
payload: {
297+
walletID: wallet.id,
298+
actionType: 'send',
299+
onSuccess: onDepositSuccess,
300+
},
301+
})
302+
}
303+
}, [dispatch, wallet.id, onDepositSuccess, multisigConfig])
258304
}
259305

260306
export const useOnDepositDialogCancel = ({

packages/neuron-ui/src/components/DepositDialog/index.tsx

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import React, { useCallback } from 'react'
1+
import React, { useCallback, useMemo } from 'react'
22
import { Slider } from 'office-ui-fabric-react'
33
import { Trans, useTranslation } from 'react-i18next'
44
import TextField from 'widgets/TextField'
55
import Spinner, { SpinnerSize } from 'widgets/Spinner'
6-
import { openExternal } from 'services/remote'
6+
import { openExternal, MultisigConfig } from 'services/remote'
77
import { localNumberFormatter, shannonToCKBFormatter } from 'utils'
8+
import getMultisigSignStatus from 'utils/getMultisigSignStatus'
89
import { Attention, Success } from 'widgets/Icons/icon'
910
import Dialog from 'widgets/Dialog'
1011
import Tooltip from 'widgets/Tooltip'
@@ -30,9 +31,10 @@ interface DepositDialogProps {
3031
isDepositing: boolean
3132
isTxGenerated: boolean
3233
suggestFeeRate: number
33-
walletID: string
34+
wallet: State.Wallet
3435
globalAPC: number
3536
onDepositSuccess: () => void
37+
multisigConfig?: MultisigConfig
3638
}
3739

3840
const RfcLink = React.memo(() => (
@@ -50,7 +52,7 @@ const RfcLink = React.memo(() => (
5052
))
5153

5254
const DepositDialog = ({
53-
walletID,
55+
wallet,
5456
balance,
5557
show,
5658
fee,
@@ -60,6 +62,7 @@ const DepositDialog = ({
6062
suggestFeeRate,
6163
globalAPC,
6264
onDepositSuccess,
65+
multisigConfig,
6366
}: DepositDialogProps) => {
6467
const [t, { language }] = useTranslation()
6568
const disabled = !isTxGenerated
@@ -69,14 +72,22 @@ const DepositDialog = ({
6972
show
7073
)
7174
const { errorMessage, maxDepositValue } = useGenerateDaoDepositTx({
72-
walletID,
75+
walletID: wallet.id,
7376
isBalanceReserved,
7477
depositValue,
7578
suggestFeeRate,
7679
showDepositDialog: show,
7780
slidePercent,
81+
multisigConfig,
7882
})
79-
const onConfirm = useOnDepositDialogSubmit({ onDepositSuccess, walletID })
83+
84+
const canSign = useMemo(() => {
85+
if (!multisigConfig) return true
86+
const multisigSignStatus = getMultisigSignStatus({ multisigConfig, addresses: wallet.addresses })
87+
return multisigSignStatus.canSign
88+
}, [multisigConfig, wallet.addresses])
89+
90+
const onConfirm = useOnDepositDialogSubmit({ onDepositSuccess, wallet, multisigConfig })
8091
const onCancel = useOnDepositDialogCancel({ onCloseDepositDialog, resetDepositValue, setIsBalanceReserved })
8192
const onSubmit = useCallback(
8293
(e: React.FormEvent) => {
@@ -105,7 +116,7 @@ const DepositDialog = ({
105116
onCancel={onCancel}
106117
onConfirm={onConfirm}
107118
cancelText={t('nervos-dao.cancel')}
108-
confirmText={t('nervos-dao.proceed')}
119+
confirmText={canSign ? t('nervos-dao.proceed') : t('nervos-dao-detail.export')}
109120
className={styles.container}
110121
>
111122
{isDepositing ? (

packages/neuron-ui/src/components/MultisigAddress/hooks.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,12 +298,58 @@ const useApproveAction = () => {
298298
}
299299
}
300300

301+
const useDaoDepositAction = () => {
302+
const [isDialogOpen, setIsDialogOpen] = useState(false)
303+
const [depositFromMultisig, setDepositFromMultisig] = useState<MultisigConfig | undefined>()
304+
const onOpenDialog = useCallback(
305+
(option: MultisigConfig) => {
306+
setIsDialogOpen(true)
307+
setDepositFromMultisig(option)
308+
},
309+
[setIsDialogOpen, setDepositFromMultisig]
310+
)
311+
const closeDialog = useCallback(() => {
312+
setIsDialogOpen(false)
313+
}, [setIsDialogOpen])
314+
315+
return {
316+
action: onOpenDialog,
317+
closeDialog,
318+
depositFromMultisig,
319+
isDialogOpen,
320+
}
321+
}
322+
323+
const useDaoWithdrawAction = () => {
324+
const [isDialogOpen, setIsDialogOpen] = useState(false)
325+
const [withdrawFromMultisig, setWithdrawFromMultisig] = useState<MultisigConfig | undefined>()
326+
const onOpenDialog = useCallback(
327+
(option: MultisigConfig) => {
328+
setIsDialogOpen(true)
329+
setWithdrawFromMultisig(option)
330+
},
331+
[setIsDialogOpen, setWithdrawFromMultisig]
332+
)
333+
const closeDialog = useCallback(() => {
334+
setIsDialogOpen(false)
335+
}, [setIsDialogOpen])
336+
337+
return {
338+
action: onOpenDialog,
339+
closeDialog,
340+
withdrawFromMultisig,
341+
isDialogOpen,
342+
}
343+
}
344+
301345
export const useActions = ({ deleteConfigById }: { deleteConfigById: (id: number) => void }) => {
302346
return {
303347
deleteAction: useDeleteAction(deleteConfigById),
304348
infoAction: useInfoAction(),
305349
sendAction: useSendAction(),
306350
approveAction: useApproveAction(),
351+
daoDepositAction: useDaoDepositAction(),
352+
daoWithdrawAction: useDaoWithdrawAction(),
307353
}
308354
}
309355

0 commit comments

Comments
 (0)