From 773c621c9108af18ccb5c188f6d1976d9ef96f51 Mon Sep 17 00:00:00 2001
From: Mehdi Torabi <46302001+mehdi-torabiv@users.noreply.github.com>
Date: Tue, 27 Aug 2024 11:33:52 +0300
Subject: [PATCH] integrate graphql to getAttestations (#48)
* integrate graphql to getAttestations
* comment unused libs
* remove unused files
* remove unused files
---
src/components/shared/CustomTable.test.tsx | 40 ---
src/libs/oci/index.ts | 23 +-
src/pages/Identifiers/Identifiers.tsx | 269 ++++++++-------------
src/pages/Permissions/Permissions.tsx | 5 +-
src/services/eas/index.ts | 10 +
src/services/eas/query.ts | 98 ++++++++
src/utils/contracts/eas/constants.ts | 4 +
7 files changed, 228 insertions(+), 221 deletions(-)
delete mode 100644 src/components/shared/CustomTable.test.tsx
create mode 100644 src/services/eas/index.ts
create mode 100644 src/services/eas/query.ts
create mode 100644 src/utils/contracts/eas/constants.ts
diff --git a/src/components/shared/CustomTable.test.tsx b/src/components/shared/CustomTable.test.tsx
deleted file mode 100644
index 182c6dd..0000000
--- a/src/components/shared/CustomTable.test.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-// CustomTable.test.tsx
-import { render, screen } from '@testing-library/react';
-import { vi } from 'vitest';
-import CustomTable, { Platform, AccessData } from './CustomTable';
-
-// Mock AccessControlButton component
-vi.mock('./AccessControlButton', () => ({
- __esModule: true,
- default: ({ hasAccess, onToggleAccess }: { hasAccess: boolean, onToggleAccess: () => void }) => (
-
- ),
-}));
-
-describe('CustomTable', () => {
- const platforms: Platform[] = [
- { name: 'Platform1', icon:
Icon1
},
- { name: 'Platform2', icon: Icon2
},
- ];
-
- const data: AccessData[] = [
- { application: 'App1', Platform1: true, Platform2: false },
- { application: 'App2', Platform1: false, Platform2: true },
- ];
-
- it('renders the table with correct headers and data', () => {
- render();
-
- expect(screen.getByText('Applications \\ Identifiers')).toBeInTheDocument();
- expect(screen.getByText('Platform1')).toBeInTheDocument();
- expect(screen.getByText('Platform2')).toBeInTheDocument();
-
- expect(screen.getByText('App1')).toBeInTheDocument();
- expect(screen.getByText('App2')).toBeInTheDocument();
-
- expect(screen.getAllByText('Revoke Access').length).toBe(2);
- expect(screen.getAllByText('Grant Access').length).toBe(2);
- });
-});
diff --git a/src/libs/oci/index.ts b/src/libs/oci/index.ts
index e2db7fa..49355a4 100644
--- a/src/libs/oci/index.ts
+++ b/src/libs/oci/index.ts
@@ -1,13 +1,15 @@
-import { Address, parseAbiItem, WalletClient } from 'viem';
-import { SchemaEncoder } from '@ethereum-attestation-service/eas-sdk';
+import { Address, parseAbiItem } from 'viem';
+import {
+ SchemaDecodedItem,
+ SchemaEncoder,
+} from '@ethereum-attestation-service/eas-sdk';
+import * as LitJsSdk from '@lit-protocol/lit-node-client';
+import { EncryptToJsonPayload, SessionSigsMap } from '@lit-protocol/types';
import { publicClient } from './client';
import sepoliaChain from '../../utils/contracts/eas/sepoliaChain.json';
-import { LitNetwork } from '@lit-protocol/constants';
-import * as LitJsSdk from '@lit-protocol/lit-node-client';
-import { sepolia } from 'viem/chains';
-import { EncryptToJsonPayload, SessionSigsMap } from '@lit-protocol/types';
+import { SCHEMA_TYPES } from '../../utils/contracts/eas/constants';
export interface IAttestation {
uid: `0x${string}`;
@@ -76,9 +78,7 @@ export const hasActiveRevocationTime = (attestations: IAttestation[]) => {
};
export const getAttestationData = (attestation: IAttestation) => {
- const schemaEncoder = new SchemaEncoder(
- 'bytes32 key, string provider, string secret'
- );
+ const schemaEncoder = new SchemaEncoder(SCHEMA_TYPES);
const decodedData = schemaEncoder.decodeData(attestation.data);
@@ -113,3 +113,8 @@ export const decryptAttestation = async (
return JSON.parse(decryptedData);
};
+
+export const decodeAttestationData = (data: string): SchemaDecodedItem[] => {
+ const schemaEncoder = new SchemaEncoder(SCHEMA_TYPES);
+ return schemaEncoder.decodeData(data);
+};
diff --git a/src/pages/Identifiers/Identifiers.tsx b/src/pages/Identifiers/Identifiers.tsx
index 9e1b053..45dbaa0 100644
--- a/src/pages/Identifiers/Identifiers.tsx
+++ b/src/pages/Identifiers/Identifiers.tsx
@@ -10,23 +10,23 @@ import {
Paper,
Box,
Avatar,
- CircularProgress,
} from '@mui/material';
import VerifiedIcon from '@mui/icons-material/Verified';
import { FaDiscord, FaGoogle } from 'react-icons/fa';
import { useNavigate } from 'react-router-dom';
-import { useEffect, useState } from 'react';
-import { decryptAttestation, getAttestations } from '../../libs/oci';
-import { useAccount } from 'wagmi';
-import useLit from '../../hooks/LitProvider';
-import useSessionSigs from '../../hooks/useSessionSigs';
-import { useSigner } from '../../utils/eas-wagmi-utils';
-import { GraphQLClient, gql } from 'graphql-request';
-import { useQuery } from '@tanstack/react-query';
-import {
- SchemaDecodedItem,
- SchemaEncoder,
-} from '@ethereum-attestation-service/eas-sdk';
+// import { useState } from 'react';
+// import { decryptAttestation, getAttestations } from '../../libs/oci';
+// import { useAccount } from 'wagmi';
+// import useLit from '../../hooks/LitProvider';
+// import useSessionSigs from '../../hooks/useSessionSigs';
+// import { useSigner } from '../../utils/eas-wagmi-utils';
+// import { GraphQLClient, gql } from 'graphql-request';
+// import { useQuery } from '@tanstack/react-query';
+// import {
+// SchemaDecodedItem,
+// SchemaEncoder,
+// } from '@ethereum-attestation-service/eas-sdk';
+import { useGetAttestations } from '../../services/eas/query';
const identifiers = [
{ name: 'Discord', icon: FaDiscord, verified: false, color: 'text-blue-500' },
@@ -34,78 +34,17 @@ const identifiers = [
];
export function Identifiers() {
- const graphQLClient = new GraphQLClient(
- 'https://sepolia.easscan.org/graphql'
- );
-
- const SCHEMA_TYPES = 'bytes32 key, string provider, string secret';
-
- const decodettestationData = (data: string): SchemaDecodedItem[] => {
- const schemaEncoder = new SchemaEncoder(SCHEMA_TYPES);
- return schemaEncoder.decodeData(data);
- };
-
- 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 = decodettestationData(attestation.data);
- console.log({ decodedData });
- });
-
- // If you want to return decoded data, you can do something like this:
- const decodedAttestations =
- result &&
- result.attestations.map((attestation: any) => ({
- ...attestation,
- decodedData: decodettestationData(attestation.data),
- }));
-
- return decodedAttestations; // or return result.attestations if you don't need the decoded data in the result
- },
- });
- };
-
- const { data, isLoading, error } = useGetAttestations();
+ const { data } = useGetAttestations();
console.log({ data });
- const { litNodeClient } = useLit();
- const { chainId } = useAccount();
- const { sessionSigs, createSessionSigs } = useSessionSigs();
- const [decryptedData, setDecryptedData] = useState(null);
+ // const { litNodeClient } = useLit();
+ // const { chainId } = useAccount();
+ // const { sessionSigs, createSessionSigs } = useSessionSigs();
+ // const [decryptedData, setDecryptedData] = useState(null);
+
+ // const signer = useSigner();
+ // const { isConnected, address } = useAccount();
- const signer = useSigner();
- const { isConnected, address } = useAccount();
const navigate = useNavigate();
const handleRevoke = (identifier: string) => {
@@ -117,107 +56,101 @@ export function Identifiers() {
navigate(`/identifiers/${identifier.toLowerCase()}/attestation`);
};
- const fetchAttestations = async () => {
- if (!address) throw new Error('No address found');
+ // const fetchAttestations = async () => {
+ // if (!address) throw new Error('No address found');
- const attestations = await getAttestations(address as `0x${string}`);
- console.log({ attestations });
+ // const attestations = await getAttestations(address as `0x${string}`);
+ // console.log({ attestations });
- return attestations;
- };
+ // return attestations;
+ // };
- useEffect(() => {
- if (isConnected && signer && chainId && litNodeClient) {
- console.log(litNodeClient, 'litNodeClient');
+ // useEffect(() => {
+ // if (isConnected && signer && chainId && litNodeClient) {
+ // console.log(litNodeClient, 'litNodeClient');
- createSessionSigs({ signer, chainId, litNodeClient });
- }
- }, [signer, isConnected, litNodeClient, chainId, createSessionSigs]);
+ // createSessionSigs({ signer, chainId, litNodeClient });
+ // }
+ // }, [signer, isConnected, litNodeClient, chainId, createSessionSigs]);
- useEffect(() => {
- if (!sessionSigs) return;
- const decrypt = async () => {
- if (!sessionSigs) throw new Error('No sessionSigs found');
+ // useEffect(() => {
+ // if (!sessionSigs) return;
+ // const decrypt = async () => {
+ // if (!sessionSigs) throw new Error('No sessionSigs found');
- const attestations = await fetchAttestations();
+ // const attestations = await fetchAttestations();
- const decryptedSecrets = await Promise.all(
- attestations.map(async (attestation) => {
- return decryptAttestation(litNodeClient, attestation, sessionSigs);
- })
- );
- setDecryptedData(decryptedSecrets);
- };
+ // const decryptedSecrets = await Promise.all(
+ // attestations.map(async (attestation) => {
+ // return decryptAttestation(litNodeClient, attestation, sessionSigs);
+ // })
+ // );
+ // setDecryptedData(decryptedSecrets);
+ // };
- decrypt();
- }, [sessionSigs]);
+ // decrypt();
+ // }, [sessionSigs]);
return (
Identifiers
- {isLoading &&
}
- {error && (
-
Failed to load attestations
- )}
- {!isLoading && !error && (
-
-
-
-
-
- Actions
-
-
-
-
- {identifiers.map((identifier, index) => (
-
-
-
-
-
-
-
- {identifier.verified && (
-
- )}
- {identifier.name}
-
- }
- style={{ marginLeft: 16 }}
+
+
+
+
+
+ Actions
+
+
+
+
+ {identifiers.map((identifier, index) => (
+
+
+
+
+
-
- {identifier.verified ? (
-
- ) : (
-
- )}
-
-
-
-
- ))}
-
- )}
+
+
+ {identifier.verified && (
+
+ )}
+ {identifier.name}
+
+ }
+ style={{ marginLeft: 16 }}
+ />
+
+ {identifier.verified ? (
+
+ ) : (
+
+ )}
+
+
+
+
+ ))}
+
);
}
diff --git a/src/pages/Permissions/Permissions.tsx b/src/pages/Permissions/Permissions.tsx
index b919617..a460beb 100644
--- a/src/pages/Permissions/Permissions.tsx
+++ b/src/pages/Permissions/Permissions.tsx
@@ -14,10 +14,7 @@ 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, {
- AccessData,
- Platform,
-} from '../../components/shared/CustomTable';
+import CustomTable from '../../components/shared/CustomTable';
interface IProvider {
uid: string;
diff --git a/src/services/eas/index.ts b/src/services/eas/index.ts
new file mode 100644
index 0000000..045fc86
--- /dev/null
+++ b/src/services/eas/index.ts
@@ -0,0 +1,10 @@
+import { GraphQLClient } from 'graphql-request';
+
+export const easBaseUrl = import.meta.env.VITE_API_GRAPHQL_URL;
+export const ATTESTER_ADDRESS = import.meta.env.VITE_EAS_ATTESTER_ADDRESS;
+
+if (!easBaseUrl) {
+ throw new Error('VITE_API_GRAPHQL_URL is not defined');
+}
+
+export const graphQLClient = new GraphQLClient(easBaseUrl);
diff --git a/src/services/eas/query.ts b/src/services/eas/query.ts
new file mode 100644
index 0000000..5592d0e
--- /dev/null
+++ b/src/services/eas/query.ts
@@ -0,0 +1,98 @@
+import { useQuery } from '@tanstack/react-query';
+import { gql } from 'graphql-request';
+import { ATTESTER_ADDRESS, graphQLClient } from '.';
+import { EAS_SCHEMA_ID } from '../../utils/contracts/eas/constants';
+
+export const useGetAttestations = () => {
+ return useQuery({
+ queryKey: ['getAttestations'],
+ queryFn: async () => {
+ const query = gql`
+ query Attestations(
+ $attester: String!
+ $recipient: String!
+ $schemaId: String!
+ ) {
+ attestations(
+ where: {
+ attester: { equals: $attester }
+ recipient: { equals: $recipient }
+ revoked: { equals: false }
+ schemaId: { equals: $schemaId }
+ }
+ ) {
+ id
+ attester
+ recipient
+ refUID
+ revocable
+ revocationTime
+ expirationTime
+ data
+ }
+ }
+ `;
+
+ const variables = {
+ attester: ATTESTER_ADDRESS,
+ recipient: '0x026B727b60D336806B87d60e95B6d7FAd2443dD6',
+ schemaId: EAS_SCHEMA_ID,
+ };
+
+ const attestedResults = await graphQLClient.request(query, variables);
+
+ console.log({ attestedResults });
+
+ return attestedResults;
+ },
+ });
+};
+
+// 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
+// },
+// });
+// };
diff --git a/src/utils/contracts/eas/constants.ts b/src/utils/contracts/eas/constants.ts
new file mode 100644
index 0000000..2311c11
--- /dev/null
+++ b/src/utils/contracts/eas/constants.ts
@@ -0,0 +1,4 @@
+export const SCHEMA_TYPES = 'bytes32 key, string provider, string secret';
+
+export const EAS_SCHEMA_ID =
+ '0x85e90e3e16d319578888790af3284fea8bca549305071531e7478e3e0b5e7d6d';