Commit 9a08b89a authored by tom goriunov's avatar tom goriunov Committed by GitHub

Change sorting of smart-contract methods to ignore case (#2409)

Fixes #2388
parent 90b760ec
......@@ -64,12 +64,12 @@ test.describe('ABI functionality', () => {
await expect(component.getByRole('button', { name: 'Connect wallet' })).toBeVisible();
await component.getByText('setReserveInterestRateStrategyAddress').click();
await expect(component.getByLabel('4.').getByRole('button', { name: 'Simulate' })).toBeEnabled();
await expect(component.getByLabel('4.').getByRole('button', { name: 'Write' })).toBeEnabled();
await expect(component.getByLabel('9.').getByRole('button', { name: 'Simulate' })).toBeEnabled();
await expect(component.getByLabel('9.').getByRole('button', { name: 'Write' })).toBeEnabled();
await component.getByText('pause').click();
await expect(component.getByLabel('7.').getByRole('button', { name: 'Simulate' })).toBeHidden();
await expect(component.getByLabel('7.').getByRole('button', { name: 'Write' })).toBeEnabled();
await expect(component.getByLabel('5.').getByRole('button', { name: 'Simulate' })).toBeHidden();
await expect(component.getByLabel('5.').getByRole('button', { name: 'Write' })).toBeEnabled();
});
test('write, no wallet client', async({ render, createSocket, mockEnvs }) => {
......@@ -86,11 +86,11 @@ test.describe('ABI functionality', () => {
await expect(component.getByRole('button', { name: 'Connect wallet' })).toBeHidden();
await component.getByText('setReserveInterestRateStrategyAddress').click();
await expect(component.getByLabel('4.').getByRole('button', { name: 'Simulate' })).toBeEnabled();
await expect(component.getByLabel('4.').getByRole('button', { name: 'Write' })).toBeDisabled();
await expect(component.getByLabel('9.').getByRole('button', { name: 'Simulate' })).toBeEnabled();
await expect(component.getByLabel('9.').getByRole('button', { name: 'Write' })).toBeDisabled();
await component.getByText('pause').click();
await expect(component.getByLabel('7.').getByRole('button', { name: 'Simulate' })).toBeHidden();
await expect(component.getByLabel('7.').getByRole('button', { name: 'Write' })).toBeDisabled();
await expect(component.getByLabel('5.').getByRole('button', { name: 'Simulate' })).toBeHidden();
await expect(component.getByLabel('5.').getByRole('button', { name: 'Write' })).toBeDisabled();
});
});
......@@ -18,7 +18,7 @@ import ContractCustomAbiAlert from './ContractCustomAbiAlert';
import ContractMethodsContainer from './ContractMethodsContainer';
import ContractMethodsFilters from './ContractMethodsFilters';
import useMethodsFilters from './useMethodsFilters';
import { enrichWithMethodId, isMethod } from './utils';
import { formatAbi } from './utils';
interface Props {
isLoading?: boolean;
......@@ -52,12 +52,7 @@ const ContractMethodsCustom = ({ isLoading: isLoadingProp }: Props) => {
contract_address_hash: addressHash,
} : undefined);
const abi = React.useMemo(() => {
return currentInfo?.abi
.filter(isMethod)
.map(enrichWithMethodId) ?? [];
}, [ currentInfo ]);
const abi = React.useMemo(() => formatAbi(currentInfo?.abi || []), [ currentInfo ]);
const filters = useMethodsFilters({ abi });
const updateButton = React.useMemo(() => {
......
......@@ -14,7 +14,7 @@ import ContractConnectWallet from './ContractConnectWallet';
import ContractMethodsContainer from './ContractMethodsContainer';
import ContractMethodsFilters from './ContractMethodsFilters';
import useMethodsFilters from './useMethodsFilters';
import { enrichWithMethodId, isMethod } from './utils';
import { formatAbi } from './utils';
interface Props {
items: Array<SmartContractMudSystemItem>;
......@@ -42,10 +42,7 @@ const ContractMethodsMudSystem = ({ items }: Props) => {
setSelectedItem(item as SmartContractMudSystemItem);
}, []);
const abi = React.useMemo(() => {
return systemInfoQuery.data?.abi?.filter(isMethod).map(enrichWithMethodId) || [];
}, [ systemInfoQuery.data?.abi ]);
const abi = React.useMemo(() => formatAbi(systemInfoQuery.data?.abi || []), [ systemInfoQuery.data?.abi ]);
const filters = useMethodsFilters({ abi });
return (
......
......@@ -13,7 +13,7 @@ import ContractConnectWallet from './ContractConnectWallet';
import ContractMethodsContainer from './ContractMethodsContainer';
import ContractMethodsFilters from './ContractMethodsFilters';
import useMethodsFilters from './useMethodsFilters';
import { enrichWithMethodId, isMethod } from './utils';
import { formatAbi } from './utils';
interface Props {
implementations: Array<AddressImplementation>;
......@@ -36,10 +36,7 @@ const ContractMethodsProxy = ({ implementations, isLoading: isInitialLoading }:
},
});
const abi = React.useMemo(() => {
return contractQuery.data?.abi?.filter(isMethod).map(enrichWithMethodId) || [];
}, [ contractQuery.data?.abi ]);
const abi = React.useMemo(() => formatAbi(contractQuery.data?.abi || []), [ contractQuery.data?.abi ]);
const filters = useMethodsFilters({ abi });
return (
......
import { Flex } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import React from 'react';
import type { SmartContractMethod } from './types';
import type { Abi } from 'viem';
import getQueryParamString from 'lib/router/getQueryParamString';
......@@ -11,9 +10,10 @@ import ContractConnectWallet from './ContractConnectWallet';
import ContractMethodsContainer from './ContractMethodsContainer';
import ContractMethodsFilters from './ContractMethodsFilters';
import useMethodsFilters from './useMethodsFilters';
import { formatAbi } from './utils';
interface Props {
abi: Array<SmartContractMethod>;
abi: Abi;
isLoading?: boolean;
}
......@@ -24,7 +24,8 @@ const ContractMethodsRegular = ({ abi, isLoading }: Props) => {
const tab = getQueryParamString(router.query.tab);
const addressHash = getQueryParamString(router.query.hash);
const filters = useMethodsFilters({ abi });
const formattedAbi = React.useMemo(() => formatAbi(abi), [ abi ]);
const filters = useMethodsFilters({ abi: formattedAbi });
return (
<Flex flexDir="column" rowGap={ 6 }>
......@@ -35,8 +36,8 @@ const ContractMethodsRegular = ({ abi, isLoading }: Props) => {
onChange={ filters.onChange }
isLoading={ isLoading }
/>
<ContractMethodsContainer isLoading={ isLoading } isEmpty={ abi.length === 0 } type={ filters.methodType }>
<ContractAbi abi={ abi } tab={ tab } addressHash={ addressHash } visibleItems={ filters.visibleItems }/>
<ContractMethodsContainer isLoading={ isLoading } isEmpty={ formattedAbi.length === 0 } type={ filters.methodType }>
<ContractAbi abi={ formattedAbi } tab={ tab } addressHash={ addressHash } visibleItems={ filters.visibleItems }/>
</ContractMethodsContainer>
</Flex>
);
......
......@@ -42,6 +42,25 @@ export const enrichWithMethodId = (method: AbiFunction | AbiFallback | AbiReceiv
}
};
const getNameForSorting = (method: SmartContractMethod | AbiFallback | AbiReceive) => {
if ('name' in method) {
return method.name;
}
return method.type === 'fallback' ? 'fallback' : 'receive';
};
export const formatAbi = (abi: Abi) => {
return abi
.filter(isMethod)
.map(enrichWithMethodId)
.sort((a, b) => {
const aName = getNameForSorting(a);
const bName = getNameForSorting(b);
return aName.localeCompare(bName);
});
};
export const TYPE_FILTER_OPTIONS: Array<{ value: MethodType; title: string }> = [
{ value: 'all', title: 'All' },
{ value: 'read', title: 'Read' },
......
......@@ -13,7 +13,6 @@ import ContractMethodsCustom from 'ui/address/contract/methods/ContractMethodsCu
import ContractMethodsMudSystem from 'ui/address/contract/methods/ContractMethodsMudSystem';
import ContractMethodsProxy from 'ui/address/contract/methods/ContractMethodsProxy';
import ContractMethodsRegular from 'ui/address/contract/methods/ContractMethodsRegular';
import { enrichWithMethodId, isMethod } from 'ui/address/contract/methods/utils';
import ContentLoader from 'ui/shared/ContentLoader';
import type { CONTRACT_MAIN_TAB_IDS } from './utils';
......@@ -68,8 +67,6 @@ export default function useContractTabs(data: Address | undefined, isPlaceholder
onSocketError: enableQuery,
});
const methods = React.useMemo(() => contractQuery.data?.abi?.filter(isMethod).map(enrichWithMethodId) ?? [], [ contractQuery.data?.abi ]);
const verifiedImplementations = React.useMemo(() => {
return data?.implementations?.filter(({ name, address }) => name && address && address !== data?.hash) || [];
}, [ data?.hash, data?.implementations ]);
......@@ -83,10 +80,10 @@ export default function useContractTabs(data: Address | undefined, isPlaceholder
component: <ContractDetails mainContractQuery={ contractQuery } channel={ channel } addressHash={ data.hash }/>,
subTabs: CONTRACT_DETAILS_TAB_IDS as unknown as Array<string>,
},
methods.length > 0 && {
contractQuery.data?.abi && {
id: [ 'read_write_contract' as const, 'read_contract' as const, 'write_contract' as const ],
title: 'Read/Write contract',
component: <ContractMethodsRegular abi={ methods } isLoading={ contractQuery.isPlaceholderData }/>,
component: <ContractMethodsRegular abi={ contractQuery.data.abi } isLoading={ contractQuery.isPlaceholderData }/>,
},
verifiedImplementations.length > 0 && {
id: [ 'read_write_proxy' as const, 'read_proxy' as const, 'write_proxy' as const ],
......@@ -112,7 +109,6 @@ export default function useContractTabs(data: Address | undefined, isPlaceholder
data?.hash,
contractQuery,
channel,
methods,
verifiedImplementations,
hasMudTab,
mudSystemsQuery.isPlaceholderData,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment