|
1 | 1 | import classNames from 'classnames'; |
2 | | -import { useEffect, useRef, useState } from 'react'; |
| 2 | +import { useEffect, useMemo, useRef, useState } from 'react'; |
3 | 3 | import { useFormContext, useWatch, type Control } from 'react-hook-form'; |
4 | 4 | import { formatUnits } from 'viem'; |
5 | 5 | import { mainnet } from 'viem/chains'; |
6 | 6 | import { useChains } from 'wagmi'; |
7 | 7 | import { Accordion, AlertCard, Button, Dropdown, IconType, Tooltip, invariant } from '../../../../../core'; |
8 | 8 | import { useGukModulesContext } from '../../../gukModulesProvider'; |
9 | | -import { SmartContractFunctionDataListItem } from '../../../smartContract/smartContractFunctionDataListItem'; |
| 9 | +import { SmartContractFunctionDataListItem } from '../../../smartContract'; |
10 | 10 | import { useProposalActionsContext } from '../proposalActionsContext'; |
11 | | -import { ProposalActionsDecoder, ProposalActionsDecoderView } from '../proposalActionsDecoder'; |
12 | | -import { ProposalActionsDecoderMode } from '../proposalActionsDecoder/proposalActionsDecoder.api'; |
13 | | -import type { IProposalAction } from '../proposalActionsDefinitions'; |
| 11 | +import { |
| 12 | + ProposalActionsDecoder, |
| 13 | + ProposalActionsDecoderMode, |
| 14 | + ProposalActionsDecoderView, |
| 15 | +} from '../proposalActionsDecoder'; |
| 16 | +import { ProposalActionTypeNoBasicView, type IProposalAction } from '../proposalActionsDefinitions'; |
14 | 17 | import type { IProposalActionsItemProps, ProposalActionsItemViewMode } from './proposalActionsItem.api'; |
15 | 18 | import { ProposalActionsItemBasicView } from './proposalActionsItemBasicView'; |
16 | 19 | import { proposalActionsItemUtils } from './proposalActionsItemUtils'; |
@@ -76,8 +79,19 @@ export const ProposalActionsItem = <TAction extends IProposalAction = IProposalA |
76 | 79 | const shouldScrollRef = useRef(false); |
77 | 80 | const supportsBasicView = CustomComponent != null || proposalActionsItemUtils.isActionSupported(action); |
78 | 81 |
|
| 82 | + // View mode support depends on action type and ABI availability. Important cases: |
| 83 | + // - Actions with a basic view: decoded and raw views enabled in "watch" mode (no edits) |
| 84 | + // - Actions without a basic view (ABI is NOT present): decoded view disabled; raw view in edit mode |
| 85 | + // - Actions without a basic view (ABI is present): decoded view enabled in edit mode; raw view in watch mode |
| 86 | + // - Exception: write actions without params show the "no params" message in decoded view; raw view in watch mode |
| 87 | + // with pre-populated data field with fn selector, because leaving the data field empty was confusing and could |
| 88 | + // cause a failure when the selector is not added manually |
| 89 | + // - RAW_CALLDATA: no params case, but decoded view disabled; raw view enabled in edit mode for calldata input |
| 90 | + // - Native transfer: basic view available; decoded view disabled; raw view in watch mode |
79 | 91 | const isAbiAvailable = action.inputData != null; |
80 | | - const supportsDecodedView = isAbiAvailable; |
| 92 | + const isRawCalldataAction = action.type === (ProposalActionTypeNoBasicView.RAW_CALLDATA as string); |
| 93 | + const isNativeTransfer = action.data === '0x'; |
| 94 | + const supportsDecodedView = isAbiAvailable && !isRawCalldataAction && !isNativeTransfer; |
81 | 95 |
|
82 | 96 | const [activeViewMode, setActiveViewMode] = useState<ProposalActionsItemViewMode>( |
83 | 97 | supportsBasicView |
@@ -152,8 +166,23 @@ export const ProposalActionsItem = <TAction extends IProposalAction = IProposalA |
152 | 166 | ]; |
153 | 167 |
|
154 | 168 | const { EDIT, WATCH, READ } = ProposalActionsDecoderMode; |
155 | | - const decodedViewMode = editMode && !supportsBasicView ? EDIT : editMode ? WATCH : READ; |
156 | | - const rawViewMode = editMode && !supportsDecodedView ? EDIT : editMode ? WATCH : READ; |
| 169 | + |
| 170 | + const decodedViewMode = useMemo(() => { |
| 171 | + if (!editMode) { |
| 172 | + return READ; |
| 173 | + } |
| 174 | + |
| 175 | + return supportsBasicView ? WATCH : EDIT; |
| 176 | + }, [EDIT, READ, WATCH, editMode, supportsBasicView]); |
| 177 | + |
| 178 | + const rawViewMode = useMemo(() => { |
| 179 | + if (!editMode) { |
| 180 | + return READ; |
| 181 | + } |
| 182 | + |
| 183 | + // There is a case when basic view is supported but not decoded view, i.e., native transfer |
| 184 | + return supportsDecodedView || supportsBasicView ? WATCH : EDIT; |
| 185 | + }, [EDIT, READ, WATCH, editMode, supportsBasicView, supportsDecodedView]); |
157 | 186 |
|
158 | 187 | return ( |
159 | 188 | <Accordion.Item value={value ?? index.toString()} ref={itemRef}> |
|
0 commit comments