From 28576035b7afc75f3e1866718cf50d4af2e3831a Mon Sep 17 00:00:00 2001 From: mehditorabiv Date: Wed, 28 Aug 2024 11:27:01 +0300 Subject: [PATCH] implement permissions --- src/components/shared/CustomTable.tsx | 19 +- src/pages/Permissions/Permissions.tsx | 285 +++++++++++++------------- src/services/eas/query.ts | 49 ----- 3 files changed, 151 insertions(+), 202 deletions(-) diff --git a/src/components/shared/CustomTable.tsx b/src/components/shared/CustomTable.tsx index bdf1b7a..4fb81cc 100644 --- a/src/components/shared/CustomTable.tsx +++ b/src/components/shared/CustomTable.tsx @@ -35,9 +35,6 @@ const CustomTable: React.FC> = ({ ycolumns, handleGrantOrRevokeAccess, }) => { - console.log('xcolumns:', xcolumns); - console.log('ycolumns:', ycolumns); - const groupedApplications = ycolumns.reduce( (acc, application) => { if (!acc[application.applicationName]) { @@ -89,12 +86,16 @@ const CustomTable: React.FC> = ({ ); return ( - - handleToggleAccess(application!, platform) - } - /> + {application ? ( + + handleToggleAccess(application, platform) + } + /> + ) : ( + No Data + )} ); })} diff --git a/src/pages/Permissions/Permissions.tsx b/src/pages/Permissions/Permissions.tsx index a460beb..b06558d 100644 --- a/src/pages/Permissions/Permissions.tsx +++ b/src/pages/Permissions/Permissions.tsx @@ -1,175 +1,172 @@ -/* eslint-disable react-hooks/exhaustive-deps */ -/* eslint-disable @typescript-eslint/no-unused-vars */ -import { - useAccount, - useReadContract, - useReadContracts, - useWriteContract, -} from 'wagmi'; -import { Abi, Address } from 'viem'; -import { useEffect, useState } from 'react'; +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { useEffect, useMemo, useState } from 'react'; +import { useReadContract, useReadContracts, useWriteContract } from 'wagmi'; +import { Address, Abi } from 'viem'; +import { Backdrop, CircularProgress, Stack, Typography } from '@mui/material'; +import { useGetAttestations } from '../../services/eas/query'; import sepoliaChainAppConctract from '../../utils/contracts/app/sepoliaChain.json'; import sepoliaChainOidonctract from '../../utils/contracts/oid/sepoliaChain.json'; -import useSessionSigs from '../../hooks/useSessionSigs'; -import useLit from '../../hooks/LitProvider'; -import { useSigner } from '../../utils/eas-wagmi-utils'; -import { decryptAttestation, getAttestations } from '../../libs/oci'; -import CustomTable from '../../components/shared/CustomTable'; - -interface IProvider { - uid: string; - provider: string; - id: string; -} +import { decodeAttestationData, IAttestation } from '../../libs/oci'; +import CustomTable, { + Platform, + AccessData, +} from '../../components/shared/CustomTable'; export function Permissions() { - const signer = useSigner(); - const { litNodeClient } = useLit(); - const { sessionSigs, createSessionSigs } = useSessionSigs(); - - const { isConnected, address, chainId } = useAccount(); - const [applicationsArgs, setApplicationsArgs] = useState<[number, number]>([ - 0, 10, - ]); - const { writeContract } = useWriteContract(); - - const [providers, setProviders] = useState([]); - const [uids, setUids] = useState([]); - - const { data: applications } = useReadContract({ - abi: sepoliaChainAppConctract.appContractABI, - address: sepoliaChainAppConctract.appContractAddress as Address, - functionName: 'getApplications', - args: applicationsArgs, - }); + const { writeContract, isPending: isWriting } = useWriteContract(); + const { data: attestationsResponse, isLoading: isLoadingAttestations } = + useGetAttestations(); + const [applicationsArgs] = useState<[number, number]>([0, 10]); + const [attestations, setAttestations] = useState< + (IAttestation & { provider?: string; id?: string })[] + >([]); + const [permissionsWithUidsAndApps, setPermissionsWithUidsAndApps] = useState< + AccessData[] + >([]); + + const { data: applications, isLoading: isLoadingApplications } = + useReadContract({ + abi: sepoliaChainAppConctract.appContractABI, + address: sepoliaChainAppConctract.appContractAddress as Address, + functionName: 'getApplications', + args: applicationsArgs, + }); useEffect(() => { - if (!isConnected) throw new Error('Wallet not connected'); - }, [isConnected, applications]); - - const contractCalls = uids.flatMap((uid) => - applications.map((application) => ({ - abi: sepoliaChainOidonctract.oidContractAbi as Abi, - address: sepoliaChainOidonctract.oidContractAddress as Address, - functionName: 'hasPermission', - args: [uid, application.account], - })) - ); - - const { data: hasPermissionsOnApp } = useReadContracts({ - contracts: contractCalls, - }); - - console.log({ hasPermissionsOnApp }); + const processAttestations = () => { + if (!attestationsResponse) { + return; + } - const permissionsWithUidsAndApps = - hasPermissionsOnApp - ?.map((permissionResult, index) => { - const uidIndex = Math.floor(index / applications.length); - const appIndex = index % applications.length; + const attestationsData = attestationsResponse.map((attestation) => { + const decodedData = decodeAttestationData(attestation.data); - if (!permissionResult || typeof permissionResult.result !== 'boolean') { - console.error( - `Unexpected result format for UID: ${uids[uidIndex]} and account: ${applications[appIndex].account}`, - permissionResult - ); - return null; - } + const providerData = decodedData.find( + (data) => data.name === 'provider' + ); return { - uid: uids[uidIndex], - account: applications[appIndex].account, - applicationName: applications[appIndex].name, - hasPermission: permissionResult.result as boolean, + ...attestation, + provider: + typeof providerData?.value.value === 'string' + ? providerData.value.value + : undefined, + decodedData, }; - }) - .filter(Boolean) || []; + }); - console.log({ permissionsWithUidsAndApps }); + setAttestations(attestationsData); + }; - // const { data: hasPermission } = useReadContract({ - // abi: sepoliaChainOidonctract.oidContractAbi, - // address: sepoliaChainOidonctract.oidContractAddress as Address, - // functionName: 'hasPermission', - // args: [uid, account], - // }); + processAttestations(); + }, [attestationsResponse]); - // useEffect(() => { - // if (!isConnected) throw new Error('Wallet not connected'); + const contractCalls = useMemo( + () => + attestations.flatMap( + (attestation) => + applications?.map((application) => ({ + abi: sepoliaChainOidonctract.oidContractAbi as Abi, + address: sepoliaChainOidonctract.oidContractAddress as Address, + functionName: 'hasPermission', + args: [attestation.id, application.account], + })) || [] + ), + [attestations, applications] + ); - // console.log({ hasPermission }); - // }, [hasPermission]); + const { data: hasPermissionsOnApp, isLoading: isLoadingPermissions } = + useReadContracts({ + contracts: contractCalls, + }); useEffect(() => { - if (isConnected && signer && chainId && litNodeClient) { - createSessionSigs({ signer, chainId, litNodeClient }); + if (hasPermissionsOnApp) { + const uids = attestations.map((attestation) => attestation.id); + + const permissions = + hasPermissionsOnApp + ?.map((permissionResult, index) => { + const uidIndex = Math.floor(index / applications.length); + const appIndex = index % applications.length; + + if ( + !permissionResult || + typeof permissionResult.result !== 'boolean' + ) { + console.error( + `Unexpected result format for UID: ${uids[uidIndex]} and account: ${applications[appIndex].account}`, + permissionResult + ); + return null; + } + + return { + uid: uids[uidIndex], + account: applications[appIndex].account, + applicationName: applications[appIndex].name, + hasPermission: permissionResult.result as boolean, + }; + }) + .filter(Boolean) || []; + + setPermissionsWithUidsAndApps(permissions); } - }, [signer, isConnected, litNodeClient, chainId, createSessionSigs]); - - const fetchAttestations = async () => { - if (!address) throw new Error('No address found'); + }, [hasPermissionsOnApp, attestations, applications]); - const attestations = await getAttestations(address as `0x${string}`); + const providers: Platform[] = attestations.map((attestation) => ({ + id: attestation.id, + provider: attestation.provider || 'Unknown', + uid: attestation.id, + })); - const filteredUids = attestations - .filter((attestation) => attestation.revocationTime === 0n) - .map((attestation) => attestation.uid); - - setUids(filteredUids); - - return attestations.filter( - (attestation) => attestation.revocationTime === 0n - ); + const handleGrantOrRevokeAccess = (application: any, platform: any) => { + writeContract({ + abi: sepoliaChainOidonctract.oidContractAbi as Abi, + address: sepoliaChainOidonctract.oidContractAddress as Address, + functionName: application.hasPermission + ? 'revokePermission' + : 'grantPermission', + args: [platform.uid, application.account], + }); }; - useEffect(() => { - const decrypt = async () => { - try { - if (!sessionSigs || !litNodeClient) - throw new Error('No sessionSigs found'); - - const attestations = await fetchAttestations(); - - const decryptedProviders = (await Promise.all( - attestations.map((attestation) => - decryptAttestation(litNodeClient, attestation, sessionSigs) - .then((result) => ({ - ...result, - uid: attestation.uid, - })) - .catch(() => null) - ) - ).then((results) => - results.filter((value) => value !== null) - )) as IProvider[]; - - setProviders(decryptedProviders); - } catch (e) { - console.log(e); - } - }; - - decrypt(); - }, [sessionSigs, litNodeClient]); - - console.log({ providers }); + const isLoading = + isWriting || + isLoadingAttestations || + isLoadingApplications || + isLoadingPermissions; return (
-
Permissions
+ theme.zIndex.drawer + 1, + background: '#fff', + color: 'black', + }} + > + + + + Loading... + + + + + Permissions + { - writeContract({ - abi: sepoliaChainOidonctract.oidContractAbi as Abi, - address: sepoliaChainOidonctract.oidContractAddress as Address, - functionName: application.hasPermission - ? 'revokePermission' - : 'grantPermission', - args: [platform.uid, application.account], - }); - }} + handleGrantOrRevokeAccess={handleGrantOrRevokeAccess} />
); diff --git a/src/services/eas/query.ts b/src/services/eas/query.ts index c5d921e..baa1885 100644 --- a/src/services/eas/query.ts +++ b/src/services/eas/query.ts @@ -53,52 +53,3 @@ export const useGetAttestations = () => { }, }); }; - -// const useGetAttestations = () => { -// return useQuery({ -// queryKey: ['getAttestations'], -// queryFn: async () => { -// const result = await graphQLClient.request(gql` -// query Attestations { -// attestations( -// where: { -// attester: { equals: "0x2d7B3e18D45846DA09D78e3644F15BD4aafa634d" } -// recipient: { -// equals: "0x026B727b60D336806B87d60e95B6d7FAd2443dD6" -// } -// revoked: { equals: false } -// schemaId: { -// equals: "0x85e90e3e16d319578888790af3284fea8bca549305071531e7478e3e0b5e7d6d" -// } -// } -// ) { -// id -// attester -// recipient -// refUID -// revocable -// revocationTime -// expirationTime -// data -// } -// } -// `); - -// // Decode each attestation's data and log it -// result.attestations.forEach((attestation: any) => { -// const decodedData = decodedAttestations(attestation.data); -// console.log({ decodedData }); -// }); - -// // If you want to return decoded data, you can do something like this: -// const decoded = -// result && -// result.attestations.map((attestation: any) => ({ -// ...attestation, -// decodedData: decodettestationData(attestation.data), -// })); - -// return decoded; // or return result.attestations if you don't need the decoded data in the result -// }, -// }); -// };