diff --git a/icons/block_countdown.svg b/icons/block_countdown.svg index a360feab17..0024e52ce9 100644 --- a/icons/block_countdown.svg +++ b/icons/block_countdown.svg @@ -1,4 +1,4 @@ - + diff --git a/mocks/contract/methods.ts b/mocks/contract/methods.ts index 492cdc7319..5fa714921c 100644 --- a/mocks/contract/methods.ts +++ b/mocks/contract/methods.ts @@ -129,6 +129,6 @@ export const write: Array = [ payable: false, stateMutability: 'nonpayable', type: 'function', - method_id: '0x06', + is_invalid: true, }, ]; diff --git a/ui/address/contract/methods/ContractAbiItem.tsx b/ui/address/contract/methods/ContractAbiItem.tsx index b831f0a15b..1aea355880 100644 --- a/ui/address/contract/methods/ContractAbiItem.tsx +++ b/ui/address/contract/methods/ContractAbiItem.tsx @@ -1,4 +1,4 @@ -import { AccordionButton, AccordionIcon, AccordionItem, AccordionPanel, Box, Tooltip, useClipboard, useDisclosure } from '@chakra-ui/react'; +import { AccordionButton, AccordionIcon, AccordionItem, AccordionPanel, Alert, Box, Tooltip, useClipboard, useDisclosure } from '@chakra-ui/react'; import React from 'react'; import { Element } from 'react-scroll'; @@ -110,14 +110,18 @@ const ContractAbiItem = ({ data, index, id, addressHash, tab, onSubmit }: Props) - + { 'is_invalid' in data && data.is_invalid ? ( + An error occurred while parsing the method signature. + ) : ( + + ) } ) } diff --git a/ui/address/contract/methods/__screenshots__/ContractMethodsRegular.pw.tsx_dark-color-mode_write-methods-dark-mode-mobile-1.png b/ui/address/contract/methods/__screenshots__/ContractMethodsRegular.pw.tsx_dark-color-mode_write-methods-dark-mode-mobile-1.png index bd55d81042..1dcd29d361 100644 Binary files a/ui/address/contract/methods/__screenshots__/ContractMethodsRegular.pw.tsx_dark-color-mode_write-methods-dark-mode-mobile-1.png and b/ui/address/contract/methods/__screenshots__/ContractMethodsRegular.pw.tsx_dark-color-mode_write-methods-dark-mode-mobile-1.png differ diff --git a/ui/address/contract/methods/__screenshots__/ContractMethodsRegular.pw.tsx_default_write-methods-dark-mode-mobile-1.png b/ui/address/contract/methods/__screenshots__/ContractMethodsRegular.pw.tsx_default_write-methods-dark-mode-mobile-1.png index 9ee796419e..e620bff054 100644 Binary files a/ui/address/contract/methods/__screenshots__/ContractMethodsRegular.pw.tsx_default_write-methods-dark-mode-mobile-1.png and b/ui/address/contract/methods/__screenshots__/ContractMethodsRegular.pw.tsx_default_write-methods-dark-mode-mobile-1.png differ diff --git a/ui/address/contract/methods/__screenshots__/ContractMethodsRegular.pw.tsx_mobile_write-methods-dark-mode-mobile-1.png b/ui/address/contract/methods/__screenshots__/ContractMethodsRegular.pw.tsx_mobile_write-methods-dark-mode-mobile-1.png index bebc3b04b5..dbe1277a94 100644 Binary files a/ui/address/contract/methods/__screenshots__/ContractMethodsRegular.pw.tsx_mobile_write-methods-dark-mode-mobile-1.png and b/ui/address/contract/methods/__screenshots__/ContractMethodsRegular.pw.tsx_mobile_write-methods-dark-mode-mobile-1.png differ diff --git a/ui/address/contract/methods/form/resultPublicClient/ItemTuple.tsx b/ui/address/contract/methods/form/resultPublicClient/ItemTuple.tsx index 56970d7f91..4b5a1f13ee 100644 --- a/ui/address/contract/methods/form/resultPublicClient/ItemTuple.tsx +++ b/ui/address/contract/methods/form/resultPublicClient/ItemTuple.tsx @@ -16,7 +16,7 @@ interface Props { const ItemTuple = ({ abiParameter, data, mode, level }: Props) => { return ( -

+

{ printRowOffset(level) } { abiParameter.name || abiParameter.internalType } @@ -36,7 +36,7 @@ const ItemTuple = ({ abiParameter, data, mode, level }: Props) => { ); }) }

{ printRowOffset(level) }{ '}' }

-

+
); }; diff --git a/ui/address/contract/methods/types.ts b/ui/address/contract/methods/types.ts index d48eb35672..1882b77a9f 100644 --- a/ui/address/contract/methods/types.ts +++ b/ui/address/contract/methods/types.ts @@ -6,8 +6,9 @@ export type MethodType = 'read' | 'write'; export type MethodCallStrategy = 'read' | 'write' | 'simulate'; export type ResultViewMode = 'preview' | 'result'; -export type SmartContractMethodRead = AbiFunction & { method_id: string }; -export type SmartContractMethodWrite = AbiFunction & { method_id: string } | AbiFallback | AbiReceive; +export type SmartContractMethodCustomFields = { method_id: string } | { is_invalid: boolean }; +export type SmartContractMethodRead = AbiFunction & SmartContractMethodCustomFields; +export type SmartContractMethodWrite = AbiFunction & SmartContractMethodCustomFields | AbiFallback | AbiReceive; export type SmartContractMethod = SmartContractMethodRead | SmartContractMethodWrite; export interface FormSubmitResultPublicClient { diff --git a/ui/address/contract/methods/useCallMethodPublicClient.ts b/ui/address/contract/methods/useCallMethodPublicClient.ts index d0be76864a..fab792816d 100644 --- a/ui/address/contract/methods/useCallMethodPublicClient.ts +++ b/ui/address/contract/methods/useCallMethodPublicClient.ts @@ -1,4 +1,5 @@ import React from 'react'; +import { getAddress } from 'viem'; import { usePublicClient } from 'wagmi'; import type { FormSubmitResult, MethodCallStrategy, SmartContractMethod } from './types'; @@ -15,7 +16,7 @@ interface Params { export default function useCallMethodPublicClient(): (params: Params) => Promise { const publicClient = usePublicClient({ chainId: Number(config.chain.id) }); - const { address } = useAccount(); + const { address: account } = useAccount(); return React.useCallback(async({ args, item, addressHash, strategy }) => { if (!('name' in item)) { @@ -26,12 +27,14 @@ export default function useCallMethodPublicClient(): (params: Params) => Promise throw new Error('Public Client is not defined'); } + const address = getAddress(addressHash); + const params = { abi: [ item ], functionName: item.name, args: args, - address: addressHash as `0x${ string }`, - account: address, + address, + account, }; const result = strategy === 'read' ? await publicClient.readContract(params) : await publicClient.simulateContract(params); @@ -40,5 +43,5 @@ export default function useCallMethodPublicClient(): (params: Params) => Promise data: strategy === 'read' ? result : result.result, }; - }, [ address, publicClient ]); + }, [ account, publicClient ]); } diff --git a/ui/address/contract/methods/utils.ts b/ui/address/contract/methods/utils.ts index 5ffb09e98b..a7f2716929 100644 --- a/ui/address/contract/methods/utils.ts +++ b/ui/address/contract/methods/utils.ts @@ -1,7 +1,8 @@ import type { Abi } from 'abitype'; +import type { AbiFunction } from 'viem'; import { toFunctionSelector } from 'viem'; -import type { SmartContractMethodRead, SmartContractMethodWrite } from './types'; +import type { SmartContractMethodCustomFields, SmartContractMethodRead, SmartContractMethodWrite } from './types'; export const getNativeCoinValue = (value: unknown) => { if (typeof value !== 'string') { @@ -25,13 +26,25 @@ export const isWriteMethod = (method: Abi[number]): method is SmartContractMetho (method.type === 'function' || method.type === 'fallback' || method.type === 'receive') && !isReadMethod(method); +const enrichWithMethodId = (method: AbiFunction): SmartContractMethodCustomFields => { + try { + return { + method_id: toFunctionSelector(method).slice(2), + }; + } catch (error) { + return { + is_invalid: true, + }; + } +}; + export function divideAbiIntoMethodTypes(abi: Abi): DividedAbi { return { read: abi .filter(isReadMethod) .map((method) => ({ ...method, - method_id: toFunctionSelector(method).slice(2), + ...enrichWithMethodId(method), })), write: abi .filter(isWriteMethod) @@ -43,7 +56,7 @@ export function divideAbiIntoMethodTypes(abi: Abi): DividedAbi { return { ...method, - method_id: toFunctionSelector(method).slice(2), + ...enrichWithMethodId(method), }; }), };