diff --git a/packages/gql/codegen.ts b/packages/gql/codegen.ts index 080ee147..a301da52 100644 --- a/packages/gql/codegen.ts +++ b/packages/gql/codegen.ts @@ -1,6 +1,7 @@ import type { CodegenConfig } from "@graphql-codegen/cli"; // Document mode is used for smaller bundle size +// https://the-guild.dev/graphql/codegen/plugins/presets/preset-client#when-to-use-a-string-documentmode // https://github.com/mswjs/msw/issues/1583 // https://github.com/dotansimha/graphql-code-generator/discussions/8707 @@ -12,7 +13,7 @@ const config: CodegenConfig = { generates: { "./src/graphql/eas/": { preset: "client", - documents: ["../../packages/ui-react/src/lib/eas/**/*.ts"], + documents: ["../../packages/ui-react/src/{lib,hooks}/eas/**/*.ts"], schema: "https://easscan.org/graphql", presetConfig: { gqlTagName: "gql", @@ -25,7 +26,7 @@ const config: CodegenConfig = { // https://discuss.ens.domains/t/ens-subgraph-migration-to-the-decentralised-version/19183 "./src/graphql/ens/": { preset: "client", - documents: ["../../packages/ui-react/src/lib/ens/**/*.ts"], + documents: ["../../packages/ui-react/src/{lib,hooks}/ens/**/*.ts"], schema: "https://api.studio.thegraph.com/query/49574/enssepolia/version/latest", presetConfig: { diff --git a/packages/gql/package.json b/packages/gql/package.json index f1602a2a..279a8786 100644 --- a/packages/gql/package.json +++ b/packages/gql/package.json @@ -5,7 +5,9 @@ "main": "index.js", "files": ["dist"], "exports": { - ".": "./src/graphql/index.ts" + ".": "./src/graphql/index.ts", + "./eas/*": "./src/graphql/eas/*.ts", + "./ens/*": "./src/graphql/ens/*.ts" }, "scripts": { "build:gql": "graphql-codegen --config codegen.ts" diff --git a/packages/gql/src/graphql/eas/gql.ts b/packages/gql/src/graphql/eas/gql.ts index 8f8a1cf4..a321272b 100644 --- a/packages/gql/src/graphql/eas/gql.ts +++ b/packages/gql/src/graphql/eas/gql.ts @@ -3,7 +3,26 @@ import * as types from './graphql'; -const documents = {} +/** + * Map of all GraphQL operations in the project. + * + * This map has several performance disadvantages: + * 1. It is not tree-shakeable, so it will include all operations in the project. + * 2. It is not minifiable, so the string of a GraphQL query will be multiple times inside the bundle. + * 3. It does not support dead code elimination, so it will add unused operations. + * + * Therefore it is highly recommended to use the babel or swc plugin for production. + */ +const documents = { + "\n query allAttestationsBy(\n $where: AttestationWhereInput\n ) {\n attestations(where: $where) {\n id\n txid\n recipient\n schema {\n index\n schemaNames {\n name\n }\n }\n time\n isOffchain\n schemaId\n attester\n }\n }\n": types.AllAttestationsByDocument, +}; + +/** + * The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function gql(source: "\n query allAttestationsBy(\n $where: AttestationWhereInput\n ) {\n attestations(where: $where) {\n id\n txid\n recipient\n schema {\n index\n schemaNames {\n name\n }\n }\n time\n isOffchain\n schemaId\n attester\n }\n }\n"): typeof import('./graphql').AllAttestationsByDocument; + + export function gql(source: string) { return (documents as any)[source] ?? {}; } diff --git a/packages/gql/src/graphql/eas/graphql.ts b/packages/gql/src/graphql/eas/graphql.ts index 3fd6403e..dcc0bbc6 100644 --- a/packages/gql/src/graphql/eas/graphql.ts +++ b/packages/gql/src/graphql/eas/graphql.ts @@ -1,4 +1,5 @@ /* eslint-disable */ +import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = Maybe; export type Exact = { [K in keyof T]: T[K] }; @@ -2849,6 +2850,13 @@ export type TimestampWhereUniqueInput = { id?: InputMaybe; }; +export type AllAttestationsByQueryVariables = Exact<{ + where?: InputMaybe; +}>; + + +export type AllAttestationsByQuery = { __typename?: 'Query', attestations: Array<{ __typename?: 'Attestation', id: string, txid: string, recipient: string, time: number, isOffchain: boolean, schemaId: string, attester: string, schema: { __typename?: 'Schema', index: string, schemaNames: Array<{ __typename?: 'SchemaName', name: string }> } }> }; + export class TypedDocumentString extends String implements DocumentTypeDecoration @@ -2863,3 +2871,23 @@ export class TypedDocumentString return this.value; } } + +export const AllAttestationsByDocument = new TypedDocumentString(` + query allAttestationsBy($where: AttestationWhereInput) { + attestations(where: $where) { + id + txid + recipient + schema { + index + schemaNames { + name + } + } + time + isOffchain + schemaId + attester + } +} + `) as unknown as TypedDocumentString; \ No newline at end of file diff --git a/packages/ui-react/src/components/attestations/attestation-badge.tsx b/packages/ui-react/src/components/attestations/attestation-badge.tsx index 94a7dc85..0571d494 100644 --- a/packages/ui-react/src/components/attestations/attestation-badge.tsx +++ b/packages/ui-react/src/components/attestations/attestation-badge.tsx @@ -1,7 +1,7 @@ import { Address } from "viem"; import { useChainId } from "wagmi"; import { Badge } from "#components/shadcn/badge"; -import { useGetAttestations } from "#hooks/eas/get-attestations"; +import { useGetAttestations } from "#hooks/eas/use-get-attestations"; // TODO export function AttestationBadge({ diff --git a/packages/ui-react/src/components/attestations/attestation-card.tsx b/packages/ui-react/src/components/attestations/attestation-card.tsx index 13c26fe6..f22433ce 100644 --- a/packages/ui-react/src/components/attestations/attestation-card.tsx +++ b/packages/ui-react/src/components/attestations/attestation-card.tsx @@ -14,7 +14,7 @@ import { } from "#components/shadcn/card"; import { Separator } from "#components/shadcn/separator"; import { Skeleton } from "#components/shadcn/skeleton"; -import { useGetAttestationWithUid } from "#hooks/eas/get-attestation-with-uid"; +import { useGetAttestationWithUid } from "#hooks/eas/use-get-attestation-with-uid.js"; import { getShortHex } from "#lib/utils/hex"; import { AttestationSchemaBadge } from "./attestation-schema-badge"; import { AttestationMeta, asAttestationMeta } from "./attestations"; diff --git a/packages/ui-react/src/components/attestations/attestations-table.tsx b/packages/ui-react/src/components/attestations/attestations-table.tsx index 162eda25..2ac1c75b 100644 --- a/packages/ui-react/src/components/attestations/attestations-table.tsx +++ b/packages/ui-react/src/components/attestations/attestations-table.tsx @@ -4,7 +4,7 @@ import { Address, fromBlobs } from "viem"; import { mainnet } from "viem/chains"; import { useChainId } from "wagmi"; import { DataTable } from "#components/data-table"; -import { useGetAttestations } from "#hooks/eas/get-attestations"; +import { useGetAttestations } from "#hooks/eas/use-get-attestations"; import { getEasscanAttestationUrl } from "#lib/eas/easscan"; import { truncate } from "#lib/utils/hex"; import { AttestationSchemaBadge } from "./attestation-schema-badge"; diff --git a/packages/ui-react/src/components/attestations/attestations.ts b/packages/ui-react/src/components/attestations/attestations.ts index 13e91f23..a4bf348e 100644 --- a/packages/ui-react/src/components/attestations/attestations.ts +++ b/packages/ui-react/src/components/attestations/attestations.ts @@ -1,6 +1,6 @@ import { format, formatDistance, subDays } from "date-fns"; import { Address } from "viem"; -import { AttestationQueryResult } from "#hooks/eas/get-attestations"; +import { AttestationQueryResult } from "#hooks/eas/use-get-attestations"; // TODO sync graphql type export const asAttestationMeta = (attestation: AttestationQueryResult) => { diff --git a/packages/ui-react/src/hooks/eas/use-attestation.ts b/packages/ui-react/src/hooks/eas/use-attestation.ts index 11c9ae39..4ffc87e6 100644 --- a/packages/ui-react/src/hooks/eas/use-attestation.ts +++ b/packages/ui-react/src/hooks/eas/use-attestation.ts @@ -12,6 +12,7 @@ import { Address, Chain, Hex, + TransactionReceipt, createWalletClient, stringToHex, zeroHash, @@ -26,6 +27,11 @@ export type UseAttestationParams = { schemaString: string; }; +export type UseAttestationReturnType = { + uids: string[]; + txnReceipt?: TransactionReceipt; +}; + export const useAttestation = (params: UseAttestationParams) => { const { account, chain, isOffchain, schemaId, schemaString } = params; const client = createWalletClient({ diff --git a/packages/ui-react/src/hooks/eas/get-attestation-with-uid.tsx b/packages/ui-react/src/hooks/eas/use-get-attestation-with-uid.tsx similarity index 54% rename from packages/ui-react/src/hooks/eas/get-attestation-with-uid.tsx rename to packages/ui-react/src/hooks/eas/use-get-attestation-with-uid.tsx index 4b67f7b0..f326fc37 100644 --- a/packages/ui-react/src/hooks/eas/get-attestation-with-uid.tsx +++ b/packages/ui-react/src/hooks/eas/use-get-attestation-with-uid.tsx @@ -1,24 +1,25 @@ -import { QueryClient, useQuery } from "@tanstack/react-query"; +import { Attestation } from "@geist/graphql/eas/graphql"; +import { QueryClient, UseQueryResult, useQuery } from "@tanstack/react-query"; import { gql, rawRequest } from "graphql-request"; import { getEasscanEndpoint } from "#lib/eas/easscan"; -export type AttestationByIdResponse = { - attestation: { - id: string; - txid: string; - recipient: string; - schema: { - index: number; - schemaNames: { - name: string; - }[]; - }; - time: string; // Assuming time is returned as a string (e.g., ISO 8601 format) - isOffchain: boolean; - schemaId: string; - attester: string; - } | null; // In case attestation can be null -}; +// export type AttestationByIdResponse = { +// attestation: { +// id: string; +// txid: string; +// recipient: string; +// schema: { +// index: number; +// schemaNames: { +// name: string; +// }[]; +// }; +// time: string; // Assuming time is returned as a string (e.g., ISO 8601 format) +// isOffchain: boolean; +// schemaId: string; +// attester: string; +// } | null; // In case attestation can be null +// }; const allAttestationsByQuery = gql` query AttestationById($where: AttestationWhereUniqueInput!) { @@ -40,17 +41,21 @@ const allAttestationsByQuery = gql` } `; +export type UseGetAttestationParams = { + uid: string; + chainId: number; +}; + +export type UseGetAttestationsReturnType = UseQueryResult; + export const createGetAttestationWithUidQueryOptions = ({ uid, chainId, -}: { - uid: string; - chainId: number; -}) => { +}: UseGetAttestationParams) => { return { queryKey: ["attestation", chainId, uid], queryFn: async () => - rawRequest( + rawRequest( `${getEasscanEndpoint(chainId)}/graphql`, allAttestationsByQuery.toString(), { @@ -65,10 +70,7 @@ export const createGetAttestationWithUidQueryOptions = ({ export const useGetAttestationWithUid = ({ uid, chainId, -}: { - uid: string; - chainId: number; -}) => { +}: UseGetAttestationParams): UseGetAttestationsReturnType => { const queryOptions = createGetAttestationWithUidQueryOptions({ uid, chainId, diff --git a/packages/ui-react/src/hooks/eas/get-attestations.int.test.tsx b/packages/ui-react/src/hooks/eas/use-get-attestations.int.test.tsx similarity index 95% rename from packages/ui-react/src/hooks/eas/get-attestations.int.test.tsx rename to packages/ui-react/src/hooks/eas/use-get-attestations.int.test.tsx index cb78645a..e4741558 100644 --- a/packages/ui-react/src/hooks/eas/get-attestations.int.test.tsx +++ b/packages/ui-react/src/hooks/eas/use-get-attestations.int.test.tsx @@ -1,6 +1,6 @@ import { mainnet, optimism } from "viem/chains"; import { describe, expect, test } from "vitest"; -import { useGetAttestations } from "./get-attestations"; +import { useGetAttestations } from "./use-get-attestations"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { renderHook, waitFor } from "@testing-library/react"; diff --git a/packages/ui-react/src/hooks/eas/get-attestations.ts b/packages/ui-react/src/hooks/eas/use-get-attestations.ts similarity index 73% rename from packages/ui-react/src/hooks/eas/get-attestations.ts rename to packages/ui-react/src/hooks/eas/use-get-attestations.ts index a8ccb3da..c9c59a7b 100644 --- a/packages/ui-react/src/hooks/eas/get-attestations.ts +++ b/packages/ui-react/src/hooks/eas/use-get-attestations.ts @@ -1,11 +1,9 @@ import { gql } from "@geist/graphql"; -import { useQuery } from "@tanstack/react-query"; +import type { Attestation } from "@geist/graphql/eas/graphql"; +import { UseQueryResult, useQuery } from "@tanstack/react-query"; import { rawRequest, request } from "graphql-request"; import { Address, Hex } from "viem"; import { getEasscanEndpoint } from "#lib/eas/easscan"; -// import { AllAttestationsByQuery } from 'node_modules/@geist/graphql/src/graphql/graphql'; - -type AllAttestationsByQuery = any; const allAttestationsByQuery = gql(` query allAttestationsBy( @@ -29,22 +27,23 @@ const allAttestationsByQuery = gql(` } `); -export type AttestationQueryResult = AllAttestationsByQuery["attestations"][0]; +export type UseGetAttestationsParams = { + chainId: number; + address: Address; +}; + +export type UseGetAttestationsReturnType = UseQueryResult; -// TODO type safety export const useGetAttestations = ({ chainId, address, -}: { - chainId: number; - address: Address; -}) => { +}: UseGetAttestationsParams): UseGetAttestationsReturnType => { // https://github.com/dotansimha/graphql-code-generator/blob/master/examples/react/tanstack-react-query/src/use-graphql.ts const results = useQuery({ queryKey: ["attestations", chainId, address], queryFn: async () => - rawRequest( + rawRequest( `${getEasscanEndpoint(chainId)}/graphql`, allAttestationsByQuery.toString(), { @@ -54,7 +53,7 @@ export const useGetAttestations = ({ }, }, }, - ), + ).then(({ data }) => data), }); return results; diff --git a/packages/ui-react/src/hooks/eas/use-upload-attestation.ts b/packages/ui-react/src/hooks/eas/use-upload-attestation.ts index 140133f4..6d31decf 100644 --- a/packages/ui-react/src/hooks/eas/use-upload-attestation.ts +++ b/packages/ui-react/src/hooks/eas/use-upload-attestation.ts @@ -1,7 +1,7 @@ import { useMutation, useQueryClient } from "@tanstack/react-query"; import { useWalletClient } from "wagmi"; import { UploadAttestationParams } from "#components/attestations/attestations"; -import { createGetAttestationWithUidQueryOptions } from "#hooks/eas/get-attestation-with-uid"; +import { createGetAttestationWithUidQueryOptions } from "#hooks/eas/use-get-attestation-with-uid.js"; import { useToast } from "#hooks/shadcn/use-toast"; import { createLighthouseParams, diff --git a/packages/ui-react/src/hooks/efp.ts b/packages/ui-react/src/hooks/efp.ts deleted file mode 100644 index e69de29b..00000000