diff --git a/src/components/transactions/ExecuteTxButton/index.tsx b/src/components/transactions/ExecuteTxButton/index.tsx index c351269fcd..302310b933 100644 --- a/src/components/transactions/ExecuteTxButton/index.tsx +++ b/src/components/transactions/ExecuteTxButton/index.tsx @@ -13,6 +13,8 @@ import Track from '@/components/common/Track' import { TX_LIST_EVENTS } from '@/services/analytics/events/txList' import { ReplaceTxHoverContext } from '../GroupedTxListItems/ReplaceTxHoverProvider' import CheckWallet from '@/components/common/CheckWallet' +import { useSafeSDK } from '@/hooks/coreSDK/safeCoreSDK' +import { getTxButtonTooltip } from '@/components/transactions/utils' const ExecuteTxButton = ({ txSummary, @@ -26,9 +28,12 @@ const ExecuteTxButton = ({ const txNonce = isMultisigExecutionInfo(txSummary.executionInfo) ? txSummary.executionInfo.nonce : undefined const isPending = useIsPending(txSummary.id) const { setSelectedTxId } = useContext(ReplaceTxHoverContext) + const safeSDK = useSafeSDK() const isNext = txNonce !== undefined && txNonce === safe.nonce - const isDisabled = !isNext || isPending + const isDisabled = !isNext || isPending || !safeSDK + + const tooltipTitle = getTxButtonTooltip('Execute', { isNext, nonce: safe.nonce, hasSafeSDK: !!safeSDK }) const onClick = (e: SyntheticEvent) => { e.stopPropagation() @@ -49,7 +54,7 @@ const ExecuteTxButton = ({ {(isOk) => ( {compact ? ( - + import('@/components/tx/modals/NewTxModal')) @@ -23,7 +25,11 @@ const RejectTxButton = ({ }): ReactElement | null => { const [open, setOpen] = useState(false) const txNonce = isMultisigExecutionInfo(txSummary.executionInfo) ? txSummary.executionInfo.nonce : undefined - const isDisabled = useIsPending(txSummary.id) + const isPending = useIsPending(txSummary.id) + const safeSDK = useSafeSDK() + const isDisabled = isPending || !safeSDK + + const tooltipTitle = getTxButtonTooltip('Replace', { hasSafeSDK: !!safeSDK }) const onClick = (e: SyntheticEvent) => { e.stopPropagation() @@ -36,7 +42,7 @@ const RejectTxButton = ({ {(isOk) => ( {compact ? ( - + diff --git a/src/components/transactions/SignTxButton/index.tsx b/src/components/transactions/SignTxButton/index.tsx index 729d3ffff9..2c0b3b4c0f 100644 --- a/src/components/transactions/SignTxButton/index.tsx +++ b/src/components/transactions/SignTxButton/index.tsx @@ -12,6 +12,8 @@ import CheckIcon from '@mui/icons-material/Check' import Track from '@/components/common/Track' import { TX_LIST_EVENTS } from '@/services/analytics/events/txList' import CheckWallet from '@/components/common/CheckWallet' +import { useSafeSDK } from '@/hooks/coreSDK/safeCoreSDK' +import { getTxButtonTooltip } from '@/components/transactions/utils' const SignTxButton = ({ txSummary, @@ -24,21 +26,24 @@ const SignTxButton = ({ const wallet = useWallet() const isSignable = isSignableBy(txSummary, wallet?.address || '') const isPending = useIsPending(txSummary.id) + const safeSDK = useSafeSDK() + + const isDisabled = !isSignable || isPending || !safeSDK + + const tooltipTitle = getTxButtonTooltip('Confirm', { hasSafeSDK: !!safeSDK }) const onClick = (e: SyntheticEvent) => { e.stopPropagation() setOpen(true) } - const isDisabled = !isSignable || isPending - return ( <> {(isOk) => ( {compact ? ( - + diff --git a/src/components/transactions/__tests__/utils.test.ts b/src/components/transactions/__tests__/utils.test.ts new file mode 100644 index 0000000000..aeea741306 --- /dev/null +++ b/src/components/transactions/__tests__/utils.test.ts @@ -0,0 +1,28 @@ +import { getTxButtonTooltip } from '../utils' + +describe('transactions utils', () => { + describe('getTooltipTitle', () => { + const disabledPropsBase = { hasSafeSDK: true } + + it('should return the enabledTitle if no disabled conditions', () => { + const enabledTitle = 'Execute' + + expect(getTxButtonTooltip(enabledTitle, disabledPropsBase)).toBe('Execute') + }) + + it('should return the not isNext message', () => { + const enabledTitle = 'Confirm' + const nonce = 2 + const disabledProps = { ...disabledPropsBase, isNext: false, nonce } + + expect(getTxButtonTooltip(enabledTitle, disabledProps)).toBe('Transaction 2 must be executed first') + }) + + it('should return the SDK not initialized message', () => { + const enabledTitle = 'Execute' + const disabledProps = { ...disabledPropsBase, hasSafeSDK: false } + + expect(getTxButtonTooltip(enabledTitle, disabledProps)).toBe('Loading') + }) + }) +}) diff --git a/src/components/transactions/utils.ts b/src/components/transactions/utils.ts new file mode 100644 index 0000000000..9f501c136d --- /dev/null +++ b/src/components/transactions/utils.ts @@ -0,0 +1,13 @@ +type DisabledPropsType = { + isNext?: boolean + nonce?: number + hasSafeSDK: boolean +} + +type EnabledTitleType = 'Execute' | 'Replace' | 'Confirm' + +export const getTxButtonTooltip = (enabledTitle: EnabledTitleType, disabledProps: DisabledPropsType) => { + const { hasSafeSDK, isNext, nonce } = disabledProps + + return isNext === false ? `Transaction ${nonce} must be executed first` : !hasSafeSDK ? 'Loading' : enabledTitle +}