From 40942e8955d046f56b3df5f5b766a20412988468 Mon Sep 17 00:00:00 2001 From: maryjanyes Date: Mon, 21 Oct 2024 14:37:10 +0300 Subject: [PATCH 1/3] feat (48829): agent stuff updates Signed-off-by: maryjanyes --- .../manage-registry/ManageRegistry.tsx | 13 +- .../manage-agents/ManageAgents.tsx | 158 +++++++++++++++--- src/hooks/useTokenIdentityRegistryAgents.ts | 37 +++- src/services/util/helpers.tsx | 10 +- src/types/types.ts | 10 ++ src/views/eip3643/EIP3643.tsx | 7 +- 6 files changed, 207 insertions(+), 28 deletions(-) diff --git a/src/components/manage-registry/ManageRegistry.tsx b/src/components/manage-registry/ManageRegistry.tsx index 068292f..31ee1cc 100644 --- a/src/components/manage-registry/ManageRegistry.tsx +++ b/src/components/manage-registry/ManageRegistry.tsx @@ -35,8 +35,16 @@ import { useTokenIdentityRegistry } from "@/hooks/useTokenIdentityRegistry"; import { useWalletInterface } from "@/services/wallets/useWalletInterface"; import { ManageAgents } from "./manage-agents/ManageAgents"; import { ManageIdentities } from "./manage-identities/ManageIdentities"; +import { encodeLogToIdentity } from "@/services/util/helpers"; +import { LogDescription } from "ethers"; -export const ManageRegistry = ({ isAgents }: { isAgents: boolean }) => { +export const ManageRegistry = ({ + isAgents, + identities, +}: { + isAgents: boolean; + identities: LogDescription[]; +}) => { const [ownTokens, setOwnTokens] = useState>([]); const [selectedIdentity, setSelectedIdentity] = useState<{ walletAddress: EvmAddress; @@ -52,6 +60,8 @@ export const ManageRegistry = ({ isAgents }: { isAgents: boolean }) => { const { isOpen, onOpen, onClose } = useDisclosure(); + const identityItems = identities.map((id) => encodeLogToIdentity(id)); + useEffect(() => { (deployedTokens as any).map((item: any) => { const tokenAddress = item["args"]?.[0]; @@ -112,6 +122,7 @@ export const ManageRegistry = ({ isAgents }: { isAgents: boolean }) => { setUpdateTxError={setUpdateTxError} setUpdateTxResult={setUpdateTxResult} registry={registry} + identityItems={identityItems} /> ) : ( void; setUpdateTxError: (err?: string) => void; onClose: () => void; registry?: EvmAddress; + identityItems: IdentityItem[]; }; export function ManageAgents({ setUpdateTxResult, setUpdateTxError, registry, + identityItems, onClose, }: ManageAgentsProps) { + const [selectedAgentToAdd, setSelectedAgentToAdd] = useState(); const [selectedAgent, setSelectedAgent] = useState(); - const [newUserAgentAddress, setNewUserAgentAddress] = useState(); - const { walletInterface } = useWalletInterface(); - const { filteredAgents } = useTokenIdentityRegistryAgents(registry); + const inputRef = useRef(null); + const [agentManualError, setAgentManualError] = useState(); + const [agentSelectError, setAgentSelectError] = useState(); + const { walletInterface, accountEvm } = useWalletInterface(); + const { filteredAgents, filteredNotAgentsYet } = + useTokenIdentityRegistryAgents( + registry, + identityItems.map((agent) => agent.identity as EvmAddress), + ); + const accountIdentity = identityItems.find( + (item) => item.wallet === accountEvm, + ); + const isAccountAgentAdmin = filteredNotAgentsYet?.includes( + accountIdentity?.identity as EvmAddress, + ); + const queryClient = useQueryClient(); const { @@ -58,7 +75,7 @@ export function ManageAgents({ mutateAsync: mutateIdentityRegistryAddAgent, isPending: isAddAgentPending, } = useMutation({ - mutationFn: async () => { + mutationFn: async (newUserAgentAddress: string) => { return writeIdentityRegistryAddAgent( walletInterface as WalletInterface, { args: [newUserAgentAddress as EvmAddress] }, @@ -67,10 +84,53 @@ export function ManageAgents({ }, }); + const addNewUserAgentAsAdmin = async () => { + if (filteredAgents.includes(selectedAgentToAdd)) { + setAgentSelectError("Agent already exists"); + + return; + } else { + setAgentSelectError(undefined); + } + + if (selectedAgentToAdd && ethers.isAddress(selectedAgentToAdd)) { + try { + const txHash = await mutateIdentityRegistryAddAgent(selectedAgentToAdd); + setUpdateTxResult(txHash); + setUpdateTxError(undefined); + setTimeout(() => { + queryClient.invalidateQueries({ + queryKey: [QueryKeys.ReadAgentInRegistry], + }); + }, 1000); + } catch (err: any) { + setUpdateTxResult(undefined); + setUpdateTxError(err); + } + + onClose(); + (inputRef.current as unknown as InputRefProps)?.setValue(undefined); + } else { + setAgentSelectError("Address is empty or not an EVM address"); + } + }; + const addNewUserAgent = async () => { - if (ethers.isAddress(newUserAgentAddress)) { + const newUserAgentAddress = (inputRef.current as unknown as InputRefProps) + ?.value; + + if (filteredAgents.includes(newUserAgentAddress)) { + setAgentManualError("Agent already exists"); + + return; + } else { + setAgentManualError(undefined); + } + + if (newUserAgentAddress && ethers.isAddress(newUserAgentAddress)) { try { - const txHash = await mutateIdentityRegistryAddAgent(); + const txHash = + await mutateIdentityRegistryAddAgent(newUserAgentAddress); setUpdateTxResult(txHash); setUpdateTxError(undefined); setTimeout(() => { @@ -82,12 +142,12 @@ export function ManageAgents({ setUpdateTxResult(undefined); setUpdateTxError(err); } + + onClose(); + (inputRef.current as unknown as InputRefProps)?.setValue(undefined); } else { - setUpdateTxError("User agent address is incorrect"); - setUpdateTxResult(undefined); + setAgentManualError("Address is empty or not an EVM address"); } - onClose(); - setNewUserAgentAddress(undefined); }; const handleAgentSelect = (agent: string) => { @@ -108,6 +168,7 @@ export function ManageAgents({ setUpdateTxResult(undefined); setUpdateTxError(err); } + onClose(); setSelectedAgent(undefined); }; @@ -118,9 +179,9 @@ export function ManageAgents({ setNewUserAgentAddress(e.target.value)} + size="md" + ref={inputRef} + placeholder="Paste user agent address manually" /> + + )} + + )} {!!filteredAgents && ( >([]); useEffect(() => { @@ -34,6 +37,33 @@ export function useTokenIdentityRegistryAgents(registry?: EvmAddress) { } }, [registry]); + const filteredNotAgentsYetQueryResult = useQueries({ + queries: (identityItems ?? []).map((agent) => ({ + queryKey: [QueryKeys.ReadAgentInRegistry, agent], + enabled: !!identityItems?.length && !!registry, + queryFn: async () => { + const isAgent = await readIdentityRegistryIsAgent( + { args: [agent] }, + registry, + ); + + return { + agent, + isAgent, + }; + }, + staleTime: Infinity, + })), + combine: (result) => { + return result + .filter( + (agent) => + !(agent.data?.isAgent as unknown as { "0": boolean })?.["0"], + ) + .map((agent) => agent.data?.agent); + }, + }); + const filteredAgentsQueryResult = useQueries({ queries: uniqueAgents.map((agent) => ({ queryKey: [QueryKeys.ReadAgentInRegistry, agent], @@ -61,5 +91,8 @@ export function useTokenIdentityRegistryAgents(registry?: EvmAddress) { }, }); - return { filteredAgents: filteredAgentsQueryResult }; + return { + filteredAgents: filteredAgentsQueryResult, + filteredNotAgentsYet: filteredNotAgentsYetQueryResult, + }; } diff --git a/src/services/util/helpers.tsx b/src/services/util/helpers.tsx index 9f3e31b..9549cf9 100644 --- a/src/services/util/helpers.tsx +++ b/src/services/util/helpers.tsx @@ -3,7 +3,8 @@ import { isNil } from "lodash"; import { VAULT_TOKEN_PRECISION_VALUE } from "@/config/constants"; import BigNumber from "bignumber.js"; import { formatUnits, parseUnits } from "viem"; -import { EvmAddress } from "@/types/types"; +import { EvmAddress, IdentityItem } from "@/types/types"; +import { LogDescription } from "ethers"; const COINGECKO_API_ENDPOINT = "https://api.coingecko.com/api/v3"; @@ -83,3 +84,10 @@ export function getFiatCurrencyRate( `${COINGECKO_API_ENDPOINT}/simple/price?ids=${coinName}&vs_currencies=${fiatName}`, ); } + +export function encodeLogToIdentity(log: LogDescription): IdentityItem { + return { + wallet: log.args[0], + identity: log.args[1], + }; +} diff --git a/src/types/types.ts b/src/types/types.ts index ea9936f..913b27f 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -41,6 +41,16 @@ export type TransferTokenFromRequest = { export type EvmAddress = `0x${string}`; +export type IdentityItem = { + wallet: string; + identity: string; +}; + +export type InputRefProps = { + value?: string; + setValue: (value?: string) => void; +}; + export type VaultInfoProps = { vaultAddress: EvmAddress; }; diff --git a/src/views/eip3643/EIP3643.tsx b/src/views/eip3643/EIP3643.tsx index 577b0c6..7757f46 100644 --- a/src/views/eip3643/EIP3643.tsx +++ b/src/views/eip3643/EIP3643.tsx @@ -15,7 +15,8 @@ import { ManageRegistry } from "@/components/manage-registry/ManageRegistry"; export default function EIP3643() { const { accountId } = useWalletInterface(); - const { setDeployedTokens, setIdentities } = useContext(Eip3643Context); + const { setDeployedTokens, setIdentities, identities } = + useContext(Eip3643Context); useEffect(() => { const unsubTokens: WatchContractEventReturnType = @@ -63,10 +64,10 @@ export default function EIP3643() { - + - + From 05326ac674f464ffb80f734ad4ae836ec94bac25 Mon Sep 17 00:00:00 2001 From: maryjanyes Date: Tue, 22 Oct 2024 17:42:58 +0300 Subject: [PATCH 2/3] feat (48829) agent stuff updates on top --- .../manage-registry/ManageRegistry.tsx | 19 ++-- .../manage-agents/ManageAgents.tsx | 96 +++++++++---------- src/hooks/useTokenIdentityRegistryAgents.ts | 51 +++------- src/types/types.ts | 5 - src/views/eip3643/EIP3643.tsx | 4 +- 5 files changed, 67 insertions(+), 108 deletions(-) diff --git a/src/components/manage-registry/ManageRegistry.tsx b/src/components/manage-registry/ManageRegistry.tsx index 31ee1cc..c44ac0a 100644 --- a/src/components/manage-registry/ManageRegistry.tsx +++ b/src/components/manage-registry/ManageRegistry.tsx @@ -23,7 +23,7 @@ import { useDisclosure, } from "@chakra-ui/react"; import { GroupBase } from "react-select"; -import { useContext, useState, useEffect } from "react"; +import { useContext, useState, useEffect, useMemo } from "react"; import { EvmAddress, TokenNameItem } from "@/types/types"; import { Eip3643Context } from "@/contexts/Eip3643Context"; import { MenuSelect } from "@/components/MenuSelect"; @@ -36,15 +36,8 @@ import { useWalletInterface } from "@/services/wallets/useWalletInterface"; import { ManageAgents } from "./manage-agents/ManageAgents"; import { ManageIdentities } from "./manage-identities/ManageIdentities"; import { encodeLogToIdentity } from "@/services/util/helpers"; -import { LogDescription } from "ethers"; -export const ManageRegistry = ({ - isAgents, - identities, -}: { - isAgents: boolean; - identities: LogDescription[]; -}) => { +export const ManageRegistry = ({ isAgents }: { isAgents: boolean }) => { const [ownTokens, setOwnTokens] = useState>([]); const [selectedIdentity, setSelectedIdentity] = useState<{ walletAddress: EvmAddress; @@ -55,12 +48,15 @@ export const ManageRegistry = ({ useTokenIdentityRegistry(selectedToken); const [updateTxResult, setUpdateTxResult] = useState(); const [updateTxError, setUpdateTxError] = useState(); - const { deployedTokens } = useContext(Eip3643Context); + const { deployedTokens, identities } = useContext(Eip3643Context); const { accountEvm } = useWalletInterface(); const { isOpen, onOpen, onClose } = useDisclosure(); - const identityItems = identities.map((id) => encodeLogToIdentity(id)); + const identityItems = useMemo( + () => identities.map((id) => encodeLogToIdentity(id)), + [identities], + ); useEffect(() => { (deployedTokens as any).map((item: any) => { @@ -123,6 +119,7 @@ export const ManageRegistry = ({ setUpdateTxResult={setUpdateTxResult} registry={registry} identityItems={identityItems} + selectedIdentity={selectedIdentity?.identityAddress} /> ) : ( void; setUpdateTxError: (err?: string) => void; onClose: () => void; - registry?: EvmAddress; identityItems: IdentityItem[]; + registry?: EvmAddress; + selectedIdentity?: EvmAddress; }; export function ManageAgents({ @@ -36,24 +37,27 @@ export function ManageAgents({ setUpdateTxError, registry, identityItems, + selectedIdentity, onClose, }: ManageAgentsProps) { const [selectedAgentToAdd, setSelectedAgentToAdd] = useState(); + const [agentToAdd, setAgentToAdd] = useState(); const [selectedAgent, setSelectedAgent] = useState(); - const inputRef = useRef(null); - const [agentManualError, setAgentManualError] = useState(); - const [agentSelectError, setAgentSelectError] = useState(); + const [agentManualError, setAgentManualError] = useState(""); + const [agentSelectError, setAgentSelectError] = useState(""); const { walletInterface, accountEvm } = useWalletInterface(); - const { filteredAgents, filteredNotAgentsYet } = - useTokenIdentityRegistryAgents( - registry, - identityItems.map((agent) => agent.identity as EvmAddress), - ); + const { filteredAgents } = useTokenIdentityRegistryAgents(registry); + const identityItemsToAddAsAgents = identityItems.filter( + (item) => !filteredAgents.find((agent) => agent === item.identity), + ); const accountIdentity = identityItems.find( - (item) => item.wallet === accountEvm, + (item) => item.wallet?.toLowerCase() === accountEvm, ); - const isAccountAgentAdmin = filteredNotAgentsYet?.includes( - accountIdentity?.identity as EvmAddress, + const isAccountAgentAdmin = useMemo( + () => + accountIdentity?.identity === selectedIdentity || + filteredAgents?.includes(accountIdentity?.identity as EvmAddress), + [filteredAgents, accountIdentity?.identity, selectedIdentity], ); const queryClient = useQueryClient(); @@ -62,6 +66,11 @@ export function ManageAgents({ mutateAsync: mutateIdentityRegistryRemoveAgent, isPending: isRemoveAgentPending, } = useMutation({ + onSuccess: () => { + queryClient.invalidateQueries({ + queryKey: [QueryKeys.ReadAgentInRegistry], + }); + }, mutationFn: async () => { return writeIdentityRegistryRemoveAgent( walletInterface as WalletInterface, @@ -75,6 +84,11 @@ export function ManageAgents({ mutateAsync: mutateIdentityRegistryAddAgent, isPending: isAddAgentPending, } = useMutation({ + onSuccess: () => { + queryClient.invalidateQueries({ + queryKey: [QueryKeys.ReadAgentInRegistry], + }); + }, mutationFn: async (newUserAgentAddress: string) => { return writeIdentityRegistryAddAgent( walletInterface as WalletInterface, @@ -90,7 +104,7 @@ export function ManageAgents({ return; } else { - setAgentSelectError(undefined); + setAgentSelectError(""); } if (selectedAgentToAdd && ethers.isAddress(selectedAgentToAdd)) { @@ -98,53 +112,38 @@ export function ManageAgents({ const txHash = await mutateIdentityRegistryAddAgent(selectedAgentToAdd); setUpdateTxResult(txHash); setUpdateTxError(undefined); - setTimeout(() => { - queryClient.invalidateQueries({ - queryKey: [QueryKeys.ReadAgentInRegistry], - }); - }, 1000); } catch (err: any) { setUpdateTxResult(undefined); setUpdateTxError(err); } onClose(); - (inputRef.current as unknown as InputRefProps)?.setValue(undefined); } else { setAgentSelectError("Address is empty or not an EVM address"); } }; const addNewUserAgent = async () => { - const newUserAgentAddress = (inputRef.current as unknown as InputRefProps) - ?.value; - - if (filteredAgents.includes(newUserAgentAddress)) { + if (filteredAgents.includes(agentToAdd as EvmAddress)) { setAgentManualError("Agent already exists"); return; } else { - setAgentManualError(undefined); + setAgentManualError(""); } - if (newUserAgentAddress && ethers.isAddress(newUserAgentAddress)) { + if (agentToAdd && ethers.isAddress(agentToAdd)) { try { - const txHash = - await mutateIdentityRegistryAddAgent(newUserAgentAddress); + const txHash = await mutateIdentityRegistryAddAgent(agentToAdd); setUpdateTxResult(txHash); setUpdateTxError(undefined); - setTimeout(() => { - queryClient.invalidateQueries({ - queryKey: [QueryKeys.ReadAgentInRegistry], - }); - }, 1000); } catch (err: any) { setUpdateTxResult(undefined); setUpdateTxError(err); } onClose(); - (inputRef.current as unknown as InputRefProps)?.setValue(undefined); + setAgentToAdd(undefined); } else { setAgentManualError("Address is empty or not an EVM address"); } @@ -156,14 +155,9 @@ export function ManageAgents({ const removeUserAgent = async () => { try { - const txHash = await mutateIdentityRegistryRemoveAgent(); + const txHash = await mutateIdentityRegistryRemoveAgent(undefined); setUpdateTxResult(txHash); setUpdateTxError(undefined); - setTimeout(() => { - queryClient.invalidateQueries({ - queryKey: [QueryKeys.ReadAgentInRegistry], - }); - }, 1000); } catch (err: any) { setUpdateTxResult(undefined); setUpdateTxError(err); @@ -180,7 +174,9 @@ export function ManageAgents({ { + setAgentToAdd((e.target as any).value); + }} placeholder="Paste user agent address manually" />