Skip to content

Commit

Permalink
Merge pull request #4155 from JoinColony/feat/3534-redo-arbitrary
Browse files Browse the repository at this point in the history
Feat/3534 redo arbitrary
  • Loading branch information
Nortsova authored Jan 31, 2025
2 parents 6417198 + 23eb4e3 commit 0a26d9f
Show file tree
Hide file tree
Showing 10 changed files with 163 additions and 94 deletions.
1 change: 1 addition & 0 deletions src/components/v5/common/ActionSidebar/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const MANAGE_MEMBERS_FIELD_NAME = 'manageMembers';
export const COLONY_NAME_FIELD_NAME = 'colonyName';
export const COLONY_AVATAR_FIELD_NAME = 'avatar';
export const COLONY_DESCRIPTION_FIELD_NAME = 'colonyDescription';
export const ARBITRARY_TRANSACTIONS_FIELD_NAME = 'transactions';
export const COLONY_OBJECTIVE_TITLE_FIELD_NAME = 'colonyObjectiveTitle';
export const COLONY_OBJECTIVE_DESCRIPTION_FIELD_NAME =
'colonyObjectiveDescription';
Expand Down
16 changes: 16 additions & 0 deletions src/components/v5/common/ActionSidebar/hooks/useGetActionData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { useGetAllTokens } from '~hooks/useGetAllTokens.ts';
import { convertRolesToArray } from '~transformers/index.ts';
import { DecisionMethod, ExtendedColonyActionType } from '~types/actions.ts';
import { Authority } from '~types/authority.ts';
import { getDecodedArbitraryTransactions } from '~utils/arbitraryTxs.ts';
import { getExtendedActionType } from '~utils/colonyActions.ts';
import { convertToDecimal } from '~utils/convertToDecimal.ts';
import { convertPeriodToHours } from '~utils/extensions.ts';
Expand All @@ -23,6 +24,7 @@ import {
import {
ACTION_TYPE_FIELD_NAME,
AMOUNT_FIELD_NAME,
ARBITRARY_TRANSACTIONS_FIELD_NAME,
FROM_FIELD_NAME,
RECIPIENT_FIELD_NAME,
TEAM_FIELD_NAME,
Expand Down Expand Up @@ -70,6 +72,7 @@ const useGetActionData = (transactionId: string | undefined) => {
isMotion,
roles,
colony,
arbitraryTransactions,
} = action;

const { metadata: expenditureMetadata, slots } = expenditure || {};
Expand Down Expand Up @@ -384,6 +387,19 @@ const useGetActionData = (transactionId: string | undefined) => {
...repeatableFields,
};
}
case ColonyActionType.MakeArbitraryTransaction:
case ColonyActionType.MakeArbitraryTransactionsMotion:
case ColonyActionType.MakeArbitraryTransactionsMultisig: {
const decodedArbitraryTransactions = getDecodedArbitraryTransactions(
arbitraryTransactions || [],
action,
);
return {
[ACTION_TYPE_FIELD_NAME]: Action.ArbitraryTxs,
[ARBITRARY_TRANSACTIONS_FIELD_NAME]: decodedArbitraryTransactions,
...repeatableFields,
};
}
default:
return undefined;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const ArbitraryTxsDescription = () => {
const { transactions } = formValues;

const firstArbitraryMethodName =
transactions?.[0]?.method.replace(/\s*\([^)]*\)/g, '') || '';
transactions?.[0]?.method?.replace(/\s*\([^)]*\)/g, '') || '';

return (
<FormattedMessage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,11 @@ export const DynamicInputs: React.FC = () => {

useEffect(() => {
// Initial render for "edit" state when we have defaultValues
if (jsonAbiField && selectedMethod) {
if (jsonAbiField) {
methodOptionsSetter({ jsonAbi: jsonAbiField });
methodArgsSetter({ jsonAbi: jsonAbiField, method: selectedMethod });
if (selectedMethod) {
methodArgsSetter({ jsonAbi: jsonAbiField, method: selectedMethod });
}
}
// This hook is intentionally called only for the first render
// Other updates will be handled in the "watch" subscription
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,8 @@ export const useGenerateABI = ({ setContractAbiLoading }) => {
const [isJsonAbiFormatted, setIsJsonAbiFormatted] = useState(false);
const [showJsonAbiEditWarning, setShowJsonAbiEditWarning] = useState(false);

useEffect(() => {
const { unsubscribe } = watch(
({ contractAddress: contractAddressField }, { name }) => {
if (name === 'contractAddress' && isAddress(contractAddressField)) {
getABIFromContractAddress(contractAddressField);

// Reset jsonAbi state if contractAddress is updated
// jsonAbi will be filled with data after a successful ABI response
setValue('jsonAbi', '');
setIsJsonAbiFormatted(false);
}
},
);

async function getABIFromContractAddress(contractAddress: string) {
const getABIFromContractAddress = useCallback(
async (contractAddress: string) => {
if (!networkInfo?.chainId) {
return;
}
Expand Down Expand Up @@ -57,12 +44,48 @@ export const useGenerateABI = ({ setContractAbiLoading }) => {
// eslint-disable-next-line no-console
console.log(e);
}
}
},
[networkInfo?.chainId, setContractAbiLoading, setValue, trigger],
);

useEffect(() => {
const { unsubscribe } = watch(
({ contractAddress: contractAddressField }, { name }) => {
if (name === 'contractAddress' && isAddress(contractAddressField)) {
getABIFromContractAddress(contractAddressField);

// Reset jsonAbi state if contractAddress is updated
// jsonAbi will be filled with data after a successful ABI response
setValue('jsonAbi', '');
setIsJsonAbiFormatted(false);
}
},
);

return () => unsubscribe();
}, [watch, networkInfo?.chainId, setContractAbiLoading, setValue, trigger]);
}, [
watch,
networkInfo?.chainId,
setContractAbiLoading,
setValue,
trigger,
getABIFromContractAddress,
]);

const jsonAbiField = watch('jsonAbi');
const contractAddressField = watch('contractAddress');

useEffect(() => {
// Initial ABI loading in case there is no ABI after REDO action
if (
contractAddressField &&
isAddress(contractAddressField) &&
!jsonAbiField
) {
getABIFromContractAddress(contractAddressField);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

const toggleJsonFormat = useCallback(() => {
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import React, { type FC } from 'react';

import { Action } from '~constants/actions.ts';
import { type ColonyAction, ColonyActionType } from '~types/graphql.ts';
import { getFormatValuesArbitraryTransactions } from '~utils/arbitraryTxs.ts';
import { formatText } from '~utils/intl.ts';
import {
ACTION_TYPE_FIELD_NAME,
ARBITRARY_TRANSACTIONS_FIELD_NAME,
DECISION_METHOD_FIELD_NAME,
DESCRIPTION_FIELD_NAME,
TITLE_FIELD_NAME,
} from '~v5/common/ActionSidebar/consts.ts';
import { useDecisionMethod } from '~v5/common/CompletedAction/hooks.ts';
import UserInfoPopover from '~v5/shared/UserInfoPopover/UserInfoPopover.tsx';

import ArbitraryTransactionsTable from '../ArbitraryTransactionsTable/index.ts';
Expand All @@ -19,11 +28,14 @@ import {
DescriptionRow,
} from '../rows/index.ts';

import { useTransformArbitraryTransactions } from './hooks.ts';

interface ArbitraryTransactionProps {
action: ColonyAction;
}

const ArbitraryTransaction: FC<ArbitraryTransactionProps> = ({ action }) => {
const decisionMethod = useDecisionMethod(action);
const {
customTitle = formatText(
{
Expand All @@ -34,15 +46,29 @@ const ArbitraryTransaction: FC<ArbitraryTransactionProps> = ({ action }) => {
},
),
} = action?.metadata || {};
const { initiatorUser, transactionHash } = action;
const { initiatorUser, transactionHash, annotation } = action;

const data = useTransformArbitraryTransactions(
action.arbitraryTransactions || [],
action,
);

const arbitraryMessageValues = getFormatValuesArbitraryTransactions(action);

return (
<>
<div className="flex items-center justify-between gap-2">
<ActionTitle>{customTitle}</ActionTitle>
<MeatballMenu showRedoItem={false} transactionHash={transactionHash} />
<MeatballMenu
transactionHash={transactionHash}
defaultValues={{
[TITLE_FIELD_NAME]: customTitle,
[ACTION_TYPE_FIELD_NAME]: Action.ArbitraryTxs,
[DECISION_METHOD_FIELD_NAME]: decisionMethod,
[DESCRIPTION_FIELD_NAME]: annotation?.message,
[ARBITRARY_TRANSACTIONS_FIELD_NAME]: data,
}}
/>
</div>
<ActionSubtitle>
{formatText(
Expand Down Expand Up @@ -78,7 +104,7 @@ const ArbitraryTransaction: FC<ArbitraryTransactionProps> = ({ action }) => {
<DescriptionRow description={action.annotation.message} />
)}

<ArbitraryTransactionsTable action={action} />
<ArbitraryTransactionsTable data={data} />
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,21 @@ import {
type ColonyActionFragment,
type ColonyActionArbitraryTransaction,
} from '~gql';
import {
getDecodedArbitraryTransactions,
type DecodedArbitraryTransaction,
} from '~utils/arbitraryTxs.ts';

export interface CompletedArbitraryTransactions
extends Partial<DecodedArbitraryTransaction> {
encodedFunction?: string;
contractAddress: string;
jsonAbi?: string;
}

export const useModifyArbitraryTransaction = (
export const useTransformArbitraryTransactions = (
data: ColonyActionArbitraryTransaction[],
action: ColonyActionFragment,
): (ColonyActionArbitraryTransaction & { action: ColonyActionFragment })[] => {
return data?.map((transaction) => {
return {
...transaction,
action,
};
});
): CompletedArbitraryTransactions[] => {
return getDecodedArbitraryTransactions(data, action);
};
Original file line number Diff line number Diff line change
@@ -1,44 +1,31 @@
import React, { type FC } from 'react';

import {
type ColonyActionArbitraryTransaction,
type ColonyActionFragment,
} from '~gql';
import { useTablet } from '~hooks/index.ts';
import { formatText } from '~utils/intl.ts';
import { Table } from '~v5/common/Table/Table.tsx';

import { useModifyArbitraryTransaction } from '../ArbitraryTransaction/hooks.ts';
import { type CompletedArbitraryTransactions } from '../ArbitraryTransaction/hooks.ts';

import { displayName } from './const.ts';
import { useArbitraryTxsTableColumns } from './hooks.tsx';

export type ArbitraryTransactionsTableItem =
ColonyActionArbitraryTransaction & {
action: ColonyActionFragment;
};
interface ArbitraryTransactionsTableProps {
action: ColonyActionFragment;
data: CompletedArbitraryTransactions[];
}

const ArbitraryTransactionsTable: FC<ArbitraryTransactionsTableProps> = ({
action,
data,
}) => {
const isTablet = useTablet();

const columns = useArbitraryTxsTableColumns();

const data = useModifyArbitraryTransaction(
action.arbitraryTransactions || [],
action,
);

return (
<div className="pt-4">
<h5 className="mb-4 text-2">
{formatText({ id: 'actionSidebar.transactions' })}
</h5>
<Table<ArbitraryTransactionsTableItem>
<Table<CompletedArbitraryTransactions>
layout={isTablet ? 'vertical' : 'horizontal'}
className="mb-6"
columns={columns}
Expand All @@ -47,7 +34,7 @@ const ArbitraryTransactionsTable: FC<ArbitraryTransactionsTableProps> = ({
visible: true,
}}
rows={{ getRowClassName: () => 'align-top' }}
data={data.length === 0 ? [{} as ArbitraryTransactionsTableItem] : data}
data={data.length === 0 ? [{} as CompletedArbitraryTransactions] : data}
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import React, { useMemo } from 'react';

import { useTablet } from '~hooks/index.ts';
import getMaskedAddress from '~shared/MaskedAddress/getMaskedAddress.ts';
import { decodeArbitraryTransaction } from '~utils/arbitraryTxs.ts';
import { formatText } from '~utils/intl.ts';
import CellDescription, {
type CellDescriptionItem,
} from '~v5/common/ActionSidebar/partials/forms/ArbitraryTxsForm/partials/ArbitraryTransactionsTable/CellDescription.tsx';
import UserAvatar from '~v5/shared/UserAvatar/UserAvatar.tsx';

import { type ArbitraryTransactionsTableItem } from './ArbitraryTransactionsTable.tsx';
import { type CompletedArbitraryTransactions } from '../ArbitraryTransaction/hooks.ts';

import { EncodedTransactionCell } from './EncodedTransactionCell.tsx';

const getValueByType = ({ type, value, isFull }) => {
Expand All @@ -27,16 +27,16 @@ const getValueByType = ({ type, value, isFull }) => {
};

export const useArbitraryTxsTableColumns = (): ColumnDef<
ArbitraryTransactionsTableItem,
CompletedArbitraryTransactions,
string
>[] => {
const columnHelper = useMemo(
() => createColumnHelper<ArbitraryTransactionsTableItem>(),
() => createColumnHelper<CompletedArbitraryTransactions>(),
[],
);
const isTablet = useTablet();

const columns: ColumnDef<ArbitraryTransactionsTableItem, string>[] = useMemo(
const columns: ColumnDef<CompletedArbitraryTransactions, string>[] = useMemo(
() => [
columnHelper.accessor('contractAddress', {
enableSorting: false,
Expand Down Expand Up @@ -75,40 +75,22 @@ export const useArbitraryTxsTableColumns = (): ColumnDef<
cell: ({ row: { original: transaction } }) => {
const data: CellDescriptionItem[] = [];

const abi = transaction.action.metadata?.arbitraryTxAbis?.find(
(abiItem) =>
abiItem.contractAddress === transaction.contractAddress,
);

if (!abi) {
return (
<EncodedTransactionCell
encodedFunction={transaction.encodedFunction}
/>
);
}

const decodedTx = decodeArbitraryTransaction(
abi.jsonAbi,
transaction.encodedFunction,
);

if (!decodedTx) {
if (transaction.encodedFunction) {
return (
<EncodedTransactionCell
encodedFunction={transaction.encodedFunction}
/>
);
}

if (decodedTx?.method) {
if (transaction.method) {
data.push({
name: 'Method',
value: decodedTx?.method,
value: transaction.method,
});
}
if (decodedTx?.args) {
decodedTx.args?.forEach(({ name, type, value }) => {
if (transaction.args) {
transaction.args?.forEach(({ name, type, value }) => {
data.push({
name: `${name} (${type})`,
value: getValueByType({
Expand Down
Loading

0 comments on commit 0a26d9f

Please sign in to comment.