Skip to content

Commit

Permalink
Make better errors (#356)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tbaut authored Sep 24, 2023
1 parent 707011a commit d724757
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 49 deletions.
2 changes: 1 addition & 1 deletion packages/ui/src/components/NewMulisigAlert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const NewMulisigAlert = ({ className = '', onClose }: Props) => {
severity="info"
>
<div className="infoText">
Your new multisig is being created. It will be available in ~30s from the dropdown.
Your new multisig is being created. It will be available in ~1min from the dropdown.
</div>
<IconButton
className="closeButton"
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/Toasts/Snackbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@ export default styled(Snackbar)`
position: fixed;
bottom: 1rem;
left: 1rem;
z-index: 2;
z-index: 9999;
`
26 changes: 15 additions & 11 deletions packages/ui/src/components/modals/ChangeMultisig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { Button } from '../library'
import { ModalCloseButton } from '../library/ModalCloseButton'
import { useGetSortAddress } from '../../hooks/useGetSortAddress'
import { useGetMultisigAddress } from '../../contexts/useGetMultisigAddress'
import BN from 'bn.js'

interface Props {
onClose: () => void
Expand Down Expand Up @@ -183,16 +184,18 @@ const ChangeMultisig = ({ onClose, className }: Props) => {
selectedMultisig
])

const { multisigProposalNeededFunds: firstCallNeededFunds } = useMultisigProposalNeededFunds({
call: firstCall,
signatories: selectedMultisig?.signatories,
threshold: oldThreshold
})
const { multisigProposalNeededFunds: secondCallNeededFunds } = useMultisigProposalNeededFunds({
call: secondCall,
signatories: newSignatories,
threshold: newThreshold
})
const { multisigProposalNeededFunds: firstCallNeededFunds, reserved: firstCallReserved } =
useMultisigProposalNeededFunds({
call: firstCall,
signatories: selectedMultisig?.signatories,
threshold: oldThreshold
})
const { multisigProposalNeededFunds: secondCallNeededFunds, reserved: secondCallReserved } =
useMultisigProposalNeededFunds({
call: secondCall,
signatories: newSignatories,
threshold: newThreshold
})
const neededBalance = useMemo(
() => firstCallNeededFunds.add(secondCallNeededFunds),
[firstCallNeededFunds, secondCallNeededFunds]
Expand Down Expand Up @@ -355,7 +358,7 @@ const ChangeMultisig = ({ onClose, className }: Props) => {
xs={12}
>
{!hasProxyEnoughFunds && (
<Alert severity="warning">
<Alert severity="error">
The pure account doesn't have enough funds. It needs at least{' '}
{formatBnBalance(proxyAdditionNeededFunds, chainInfo?.tokenDecimals, {
tokenSymbol: chainInfo?.tokenSymbol
Expand Down Expand Up @@ -421,6 +424,7 @@ const ChangeMultisig = ({ onClose, className }: Props) => {
balanceMin={neededBalance}
isBalanceError={!hasSignerEnoughFunds}
selectedMultisig={selectedMultisig}
reservedBalance={firstCallReserved.add(secondCallReserved)}
/>
)}
{(currentStep === 'call1' || currentStep === 'call2') && (
Expand Down
55 changes: 38 additions & 17 deletions packages/ui/src/components/modals/ProposalSigning.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CircularProgress, Dialog, DialogContent, DialogTitle, Grid } from '@mui/material'
import { Alert, CircularProgress, Dialog, DialogContent, DialogTitle, Grid } from '@mui/material'
import { Button, TextFieldStyled } from '../library'
import { ChangeEvent, useCallback, useEffect, useMemo, useState } from 'react'
import { styled } from '@mui/material/styles'
Expand All @@ -17,6 +17,8 @@ import { getDisplayArgs, getExtrinsicName } from '../../utils'
import { useCallInfoFromCallData } from '../../hooks/useCallInfoFromCallData'
import { ModalCloseButton } from '../library/ModalCloseButton'
import { useGetSortAddress } from '../../hooks/useGetSortAddress'
import { useCheckBalance } from '../../hooks/useCheckBalance'
import BN from 'bn.js'

export interface SigningModalProps {
onClose: () => void
Expand Down Expand Up @@ -54,6 +56,10 @@ const ProposalSigning = ({
const { callInfo, isGettingCallInfo } = useCallInfoFromCallData(
proposalData.callData || addedCallData
)
const { hasEnoughFreeBalance: hasSignerEnoughFunds } = useCheckBalance({
min: new BN(0),
address: selectedAccount?.address
})
const mustSubmitCallData = useMemo(() => {
// the proposer can only reject, and the calldata isn't needed for this
if (isProposerSelected) return false
Expand Down Expand Up @@ -85,6 +91,17 @@ const ProposalSigning = ({
}
}, [callInfo, proposalData])

useEffect(() => {
if (hasSignerEnoughFunds) {
setErrorMessage('')
return
}

setErrorMessage(
"The selected signer doesn't have enough funds to pay for the transaction fees."
)
}, [hasSignerEnoughFunds])

const onSign = useCallback(
async (isApproving: boolean) => {
const otherSigners = getSortAddress(
Expand Down Expand Up @@ -141,9 +158,9 @@ const ProposalSigning = ({
return
}

// In case the tx has been approved between the last couple block
// In case the tx has been approved between the last couple blocks
// and the tx in the indexer hasn't been updated we should query the latest state
// right before sending the tx.
// right before sending the tx to have the right amount of signers.
const callStorage = await api.query.multisig.multisigs.entries(multisig.address)

let amountOfSigner = 0
Expand Down Expand Up @@ -309,7 +326,7 @@ const ProposalSigning = ({
/>
</>
)}
{!!callInfo?.call && !errorMessage && (
{!!callInfo?.call && (
<>
<Grid
item
Expand Down Expand Up @@ -337,19 +354,23 @@ const ProposalSigning = ({
</Grid>
</>
)}
<Grid
item
xs={0}
md={1}
/>
<Grid
item
xs={12}
md={11}
className="errorMessage"
>
{!!errorMessage && errorMessage}
</Grid>
{!!errorMessage && (
<>
<Grid
item
xs={0}
md={1}
/>
<Grid
item
xs={12}
md={11}
className="errorMessage"
>
<Alert severity="error">{errorMessage}</Alert>
</Grid>
</>
)}
<Grid
item
xs={12}
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/contexts/ToastContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const ToastProvider: React.FC<React.PropsWithChildren> = ({ children }) => {
export const useToasts = () => {
const context = useContext(ToastContext)
if (context === undefined) {
throw new Error('useToasst must be used within a ToastContextProvider')
throw new Error('useToast must be used within a ToastContextProvider')
}
return context
}
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/hooks/useCheckBalance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const useCheckBalance = ({ min, address }: Props) => {

const hasEnoughFreeBalance = useMemo(() => {
if (!address || !min || !balance) return false
return balance.gte(min)
return balance.gt(min)
}, [address, min, balance])

return { hasEnoughFreeBalance }
Expand Down
4 changes: 3 additions & 1 deletion packages/ui/src/hooks/usePureProxyCreationNeededFunds.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import BN from 'bn.js'
export const usePureProxyCreationNeededFunds = () => {
const { api, chainInfo } = useApi()
const [min, setMin] = useState(new BN(0))
const [reserved, setReserved] = useState(new BN(0))

useEffect(() => {
if (!api) return
Expand All @@ -27,9 +28,10 @@ export const usePureProxyCreationNeededFunds = () => {
// play safe and add the existential deposit twice which should suffice
const survive = (api.consts.balances.existentialDeposit as unknown as BN).muln(2)

setReserved(reserved)
setMin(reserved.add(survive))
// console.log('reserved Pure Creation', formatBnBalance(reserved.add(survive), chainInfo.tokenDecimals, { tokenSymbol: chainInfo?.tokenSymbol, numberAfterComma: 3 }))
}, [api, chainInfo])

return { pureProxyCreationNeededFunds: min }
return { pureProxyCreationNeededFunds: min, reserved }
}
44 changes: 34 additions & 10 deletions packages/ui/src/pages/Creation/Summary.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Alert, Box, Chip, Paper } from '@mui/material'
import { useMemo } from 'react'
import { useEffect, useMemo, useState } from 'react'
import { styled } from '@mui/material/styles'
import AccountDisplay from '../../components/AccountDisplay'
import SignerSelection from '../../components/select/SignerSelection'
Expand All @@ -19,6 +19,7 @@ interface Props {
proxyAddress?: string
isCreationSummary?: boolean
balanceMin?: BN
reservedBalance: BN
isBalanceError?: boolean
selectedMultisig?: MultiProxy['multisigs'][0] // this is only relevant for swaps
withProxy?: boolean
Expand All @@ -36,10 +37,40 @@ const Summary = ({
isBalanceError,
selectedMultisig,
withProxy = true,
isSubmittingExtrinsic = false
isSubmittingExtrinsic = false,
reservedBalance
}: Props) => {
const { ownAddressList } = useAccounts()
const { chainInfo } = useApi()
const [errorMessage, setErrorMessage] = useState('')

useEffect(() => {
if (!isBalanceError) {
setErrorMessage('')
return
}

const requiredBalanceString =
balanceMin &&
formatBnBalance(balanceMin, chainInfo?.tokenDecimals, {
tokenSymbol: chainInfo?.tokenSymbol
})

const reservedString = reservedBalance.isZero()
? ''
: formatBnBalance(reservedBalance, chainInfo?.tokenDecimals, {
tokenSymbol: chainInfo?.tokenSymbol
})

const reservedMessage = reservedString
? `Note that it includes ${reservedString} that will be reserved. ${
!isCreationSummary ? 'It will be returned upon transaction approval/rejection' : ''
}`
: ''
setErrorMessage(
`The selected signer doesn't have the required ${requiredBalanceString} to submit this transaction. ${reservedMessage}`
)
}, [balanceMin, chainInfo, isBalanceError, isCreationSummary, reservedBalance])

const possibleSigners = useMemo(() => {
return isCreationSummary
Expand Down Expand Up @@ -120,14 +151,7 @@ const Summary = ({
possibleSigners={possibleSigners}
/>
</Box>
{isBalanceError && balanceMin && !isSubmittingExtrinsic && (
<Alert severity="error">
The selected signer requires at least{' '}
{formatBnBalance(balanceMin, chainInfo?.tokenDecimals, {
tokenSymbol: chainInfo?.tokenSymbol
})}
</Alert>
)}
{!!errorMessage && !isSubmittingExtrinsic && <Alert severity="error">{errorMessage}</Alert>}
</Box>
)
}
Expand Down
15 changes: 9 additions & 6 deletions packages/ui/src/pages/Creation/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ const MultisigCreation = ({ className }: Props) => {
[ownAddressList, signatories]
)
const [errorMessage, setErrorMessage] = useState('')
const { pureProxyCreationNeededFunds } = usePureProxyCreationNeededFunds()
const { pureProxyCreationNeededFunds, reserved: proxyReserved } =
usePureProxyCreationNeededFunds()
const supportsProxy = useMemo(() => {
const hasProxyPallet = !!api && !!api.tx.proxy
// Moonbeam and moonriver have the pallet, but it's deactivated
Expand Down Expand Up @@ -151,11 +152,12 @@ const MultisigCreation = ({ className }: Props) => {
withProxy
])

const { multisigProposalNeededFunds } = useMultisigProposalNeededFunds({
threshold,
signatories,
call: withProxy ? batchCall : remarkCall
})
const { multisigProposalNeededFunds, reserved: multisigReserved } =
useMultisigProposalNeededFunds({
threshold,
signatories,
call: withProxy ? batchCall : remarkCall
})
const neededBalance = useMemo(
() =>
withProxy
Expand Down Expand Up @@ -413,6 +415,7 @@ const MultisigCreation = ({ className }: Props) => {
threshold={threshold}
name={name}
isBalanceError={!hasSignerEnoughFunds}
reservedBalance={withProxy ? multisigReserved.add(proxyReserved) : multisigReserved}
balanceMin={neededBalance}
withProxy={withProxy}
isSubmittingExtrinsic={isSubmitted}
Expand Down

0 comments on commit d724757

Please sign in to comment.