Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
e7c008c
feat: integrate The Graph support into EAS client
robbeverhelst Aug 11, 2025
f21cf2c
Merge branch 'main' into fix/eas-thegraph
roderik Aug 17, 2025
49ebfe3
feat(workflows): enable environment variable export for secrets loading
roderik Aug 17, 2025
2d82eb0
chore: update docs [skip ci]
roderik Aug 17, 2025
a349fb7
feat(qa): add slug/short variable injection step to workflow
roderik Aug 17, 2025
9e521cb
chore(deps): pin rlespinasse/github-slug-action action to c33ff65 (#1…
renovate[bot] Aug 17, 2025
64c80fb
refactor: reorganize imports and update transport configuration for w…
roderik Aug 18, 2025
cba36d8
chore: update package versions [skip ci]
roderik Aug 18, 2025
3672801
feat: support HA Hasura (#1120)
snigdha920 Aug 18, 2025
02b0ceb
chore: update package versions [skip ci]
snigdha920 Aug 18, 2025
a206d06
chore(deps): update dependency viem to v2.34.0 (#1256)
renovate[bot] Aug 19, 2025
3c0ebe9
fix: update viem to use latest signer json rpc endpoints (#1257)
janb87 Aug 19, 2025
491b624
chore: update docs [skip ci]
janb87 Aug 19, 2025
01aa92e
feat(cli): add Bun SQL support and environment variable validation to…
roderik Aug 19, 2025
d101259
chore: update docs [skip ci]
roderik Aug 19, 2025
d4098aa
chore: update package versions [skip ci]
roderik Aug 19, 2025
f13b6a7
chore(deps): update dependency yoctocolors to v2.1.2 (#1259)
renovate[bot] Aug 20, 2025
3386506
fix: wallet verification types (#1260)
janb87 Aug 20, 2025
ad111ca
chore: update docs [skip ci]
janb87 Aug 20, 2025
12b6d26
chore: update package versions [skip ci]
janb87 Aug 20, 2025
3845d8a
chore(deps): update dependency knip to v5.63.0 (#1262)
renovate[bot] Aug 22, 2025
81f7463
fix: update portal utils to use challenge id for wallet verification …
janb87 Aug 22, 2025
e604503
fix: docs generation
janb87 Aug 22, 2025
726bed4
chore: update package versions [skip ci]
janb87 Aug 22, 2025
392afe4
chore(deps): update dependency @modelcontextprotocol/sdk to v1.17.4 (…
renovate[bot] Aug 23, 2025
0171839
chore(deps): update dependency undici to v7.15.0 (#1264)
renovate[bot] Aug 23, 2025
897d246
chore(deps): update dependency @biomejs/biome to v2.2.2 (#1244)
renovate[bot] Aug 23, 2025
3237aba
chore(deps): update dependency @inquirer/input to v4.2.2 (#1266)
renovate[bot] Aug 25, 2025
c068ec2
chore(deps): update dependency viem to v2.35.1 (#1270)
renovate[bot] Aug 25, 2025
d7d769b
chore(deps): update dependency @inquirer/password to v4.0.18 (#1267)
renovate[bot] Aug 25, 2025
072d6e1
chore(deps): update dependency @inquirer/confirm to v5.1.16 (#1265)
renovate[bot] Aug 25, 2025
e4798ad
chore(deps): update dependency @inquirer/core to v10.2.0 (#1269)
renovate[bot] Aug 25, 2025
c07c52c
chore(deps): update dependency @inquirer/select to v4.3.2 (#1268)
renovate[bot] Aug 25, 2025
6acb92e
chore(deps): update dependency @types/bun to v1.2.21 (#1271)
renovate[bot] Aug 26, 2025
3e80644
chore(deps): update dependency typedoc to v0.28.11 (#1272)
renovate[bot] Aug 26, 2025
b873421
chore: update docs [skip ci]
renovate[bot] Aug 26, 2025
a397b1d
chore(deps): update dependency viem to v2.36.0 (#1273)
renovate[bot] Aug 28, 2025
90af661
chore(deps): update node.js to v24.7.0 (#1274)
renovate[bot] Aug 28, 2025
7e21d52
chore(deps): update namespacelabs/nscloud-cache-action digest to a289…
renovate[bot] Aug 31, 2025
2aa8063
chore(deps): update dependency @npmcli/package-json to v7 (#1276)
renovate[bot] Aug 31, 2025
683f19f
chore: update package versions [skip ci]
roderik Aug 31, 2025
3b8b564
chore(deps): update dependency typedoc to v0.28.12 (#1277)
renovate[bot] Sep 2, 2025
01e81cd
chore(deps): update dependency viem to v2.37.0 (#1278)
renovate[bot] Sep 2, 2025
f23b11d
chore(deps): update dependency @modelcontextprotocol/sdk to v1.17.5 (…
renovate[bot] Sep 3, 2025
f5b243f
chore(deps): update dependency viem to v2.37.2 (#1280)
renovate[bot] Sep 3, 2025
039dc56
feat: enhance EAS SDK with subgraph deployment capabilities
robbeverhelst Sep 10, 2025
ce88136
feat: add eth_sign rpc method to viem client (#1281)
janb87 Sep 3, 2025
3b46e8c
chore: update docs [skip ci]
janb87 Sep 3, 2025
f3212b5
chore: update package versions [skip ci]
janb87 Sep 3, 2025
ed5daff
fix: e2e tests
janb87 Sep 3, 2025
a1956e3
chore(deps): update dependency @types/semver to v7.7.1 (#1282)
renovate[bot] Sep 4, 2025
536f1ff
chore(deps): update dependency knip to v5.63.1 (#1283)
renovate[bot] Sep 4, 2025
dffd89d
chore(deps): update dependency viem to v2.37.3 (#1286)
renovate[bot] Sep 4, 2025
be41a39
chore(deps): update dependency @types/node to v24.3.1 (#1285)
renovate[bot] Sep 4, 2025
bf5b47a
chore(deps): update actions/setup-node action to v5 (#1287)
renovate[bot] Sep 4, 2025
7887161
chore(deps): update dependency @biomejs/biome to v2.2.3 (#1288)
renovate[bot] Sep 5, 2025
fbc830f
chore(deps): update dependency viem to v2.37.4 (#1290)
renovate[bot] Sep 7, 2025
f5c640f
chore(deps): update dependency @graphql-tools/url-loader to v9 (#1289)
renovate[bot] Sep 9, 2025
de359a4
chore(deps): update dependency viem to v2.37.5 (#1291)
renovate[bot] Sep 9, 2025
2cf73de
chore(deps): update dependency tsdown to ^0.15.0 (#1292)
renovate[bot] Sep 9, 2025
75464f3
chore(deps): update dependency undici to v7.16.0 (#1293)
renovate[bot] Sep 9, 2025
aac4392
fix: add includePredeployedContracts option for deploying a new netwo…
janb87 Sep 10, 2025
1aebb7d
fix: hasura e2e test (#1294)
janb87 Sep 10, 2025
a1816f0
chore(deps): update dependency @biomejs/biome to v2.2.4 (#1295)
renovate[bot] Sep 10, 2025
4efab84
chore(deps): update node.js to v24.8.0 (#1296)
renovate[bot] Sep 10, 2025
7e2352c
fix: test hangs on bun install step
janb87 Sep 11, 2025
2957a77
chore(deps): update dependency @modelcontextprotocol/sdk to v1.18.0 (…
renovate[bot] Sep 11, 2025
3ae1093
chore(deps): update dependency @types/node to v24.3.3 (#1298)
renovate[bot] Sep 13, 2025
7a6a712
chore(deps): update dependency commander to v14.0.1 (#1299)
renovate[bot] Sep 13, 2025
5abdb50
chore(deps): update dependency @types/node to v24.4.0 (#1300)
renovate[bot] Sep 14, 2025
f0165b5
chore(deps): update dependency @inquirer/confirm to v5.1.17 (#1301)
renovate[bot] Sep 14, 2025
4a058b2
chore(deps): update dependency bun to v1.2.22 (#1306)
renovate[bot] Sep 14, 2025
a560d1b
chore(deps): update dependency @inquirer/core to v10.2.2 (#1302)
renovate[bot] Sep 14, 2025
94771a0
chore(deps): update dependency @inquirer/confirm to v5.1.18 (#1307)
renovate[bot] Sep 14, 2025
3eeeb90
chore(deps): update dependency @inquirer/select to v4.3.4 (#1305)
renovate[bot] Sep 14, 2025
9dac83d
chore(deps): update dependency @inquirer/password to v4.0.20 (#1304)
renovate[bot] Sep 15, 2025
ab871b2
chore(deps): update dependency typedoc to v0.28.13 (#1309)
renovate[bot] Sep 15, 2025
ef5913c
chore(deps): update dependency @inquirer/input to v4.2.4 (#1303)
renovate[bot] Sep 15, 2025
27665ac
chore(deps): update dependency viem to v2.37.6 (#1310)
renovate[bot] Sep 16, 2025
07f1627
chore(deps): update dependency @types/node to v24.5.0 (#1311)
renovate[bot] Sep 16, 2025
14c645b
chore(deps): update dependency @types/node to v24.5.2 (#1312)
renovate[bot] Sep 18, 2025
2d2b6fc
feat: enhance EAS SDK with subgraph deployment capabilities
robbeverhelst Sep 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sdk/eas/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"devDependencies": {},
"dependencies": {
"@settlemint/sdk-portal": "workspace:*",
"@settlemint/sdk-thegraph": "workspace:*",
"@settlemint/sdk-utils": "workspace:*",
"gql.tada": "^1",
"viem": "^2",
Expand Down
10 changes: 3 additions & 7 deletions sdk/eas/src/eas.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -361,15 +361,11 @@ describe("EAS Portal Client", () => {
expect(timestamp).toBe(BigInt(1640995200));
});

test("should throw error on bulk query methods", async () => {
test("should throw error on bulk query methods when The Graph not configured", async () => {
const client = createEASClient(optionsWithAddresses);

await expect(client.getSchemas()).rejects.toThrow(
"Schema listing not implemented yet. Portal's direct contract queries don't support listing all schemas",
);
await expect(client.getAttestations()).rejects.toThrow(
"Attestation listing not implemented yet. Portal's direct contract queries don't support listing all attestations",
);
await expect(client.getSchemas()).rejects.toThrow("Schema listing requires The Graph configuration");
await expect(client.getAttestations()).rejects.toThrow("Attestation listing requires The Graph configuration");
});

test("should throw error when trying to query without contract addresses", async () => {
Expand Down
120 changes: 113 additions & 7 deletions sdk/eas/src/eas.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createPortalClient, waitForTransactionReceipt } from "@settlemint/sdk-portal";
import { createTheGraphClient, type ResultOf } from "@settlemint/sdk-thegraph";
import { createLogger, requestLogger } from "@settlemint/sdk-utils/logging";
import { validate } from "@settlemint/sdk-utils/validation";
import type { Address, Hex } from "viem";
Expand Down Expand Up @@ -46,6 +47,7 @@ export class EASClient {
private readonly portalClient: PortalClient["client"];
private readonly portalGraphql: PortalClient["graphql"];
private deployedAddresses?: DeploymentResult;
private theGraph?: ReturnType<typeof createTheGraphClient<any>>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using any when creating the The Graph client (createTheGraphClient<any>) disables the type-safety features of gql.tada. This leads to any types for query results downstream, forcing the use of unsafe type casts like (result as any).schemas to access the data.

While this might be a pragmatic choice to avoid making the EASClient generic over the subgraph schema, it's a significant trade-off that reduces maintainability and increases the risk of runtime errors if the GraphQL schema changes. It would be beneficial to explore ways to provide stronger types here.


/**
* Create a new EAS client instance
Expand Down Expand Up @@ -74,6 +76,19 @@ export class EASClient {

this.portalClient = portalClient;
this.portalGraphql = portalGraphql;

// Initialize The Graph client if configured
if (this.options.theGraph) {
this.theGraph = createTheGraphClient<any>(
{
instances: this.options.theGraph.instances,
accessToken: this.options.theGraph.accessToken,
subgraphName: this.options.theGraph.subgraphName,
cache: this.options.theGraph.cache,
},
undefined,
);
}
}

/**
Expand Down Expand Up @@ -538,9 +553,38 @@ export class EASClient {
* Consider using getSchema() for individual schema lookups.
*/
public async getSchemas(_options?: GetSchemasOptions): Promise<SchemaData[]> {
throw new Error(
"Schema listing not implemented yet. Portal's direct contract queries don't support listing all schemas. Use getSchema() for individual schema lookups or implement The Graph subgraph integration for bulk queries.",
);
if (!this.theGraph) {
throw new Error(
"Schema listing requires The Graph configuration. Provide 'theGraph' options when creating EAS client.",
);
}

// Basic listing without filters. Pagination can be added via @fetchAll directive.
const query = this.theGraph.graphql(`
query ListSchemas($first: Int = 100, $skip: Int = 0) {
schemas(first: $first, skip: $skip) @fetchAll {
id
resolver
revocable
schema
}
}
`);

const result = (await this.theGraph.client.request(query)) as ResultOf<typeof query>;
const list = (result as any).schemas as Array<{
id: string;
resolver: string;
revocable: boolean;
schema: string | null;
}>;

return list.map((s) => ({
uid: s.id as Hex,
resolver: s.resolver as Address,
revocable: Boolean(s.revocable),
schema: s.schema ?? "",
}));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The getSchemas method accepts an _options parameter (which includes limit and offset for pagination), but these options are not passed to the GraphQL request. The request is always sent without variables, so it will use the default first: 100 and skip: 0 defined in the query, ignoring any pagination options provided by the user. This makes the pagination feature non-functional.

  public async getSchemas(options?: GetSchemasOptions): Promise<SchemaData[]> {
    if (!this.theGraph) {
      throw new Error(
        "Schema listing requires The Graph configuration. Provide 'theGraph' options when creating EAS client.",
      );
    }

    // Basic listing without filters. Pagination can be added via @fetchAll directive.
    const query = this.theGraph.graphql(`
      query ListSchemas($first: Int = 100, $skip: Int = 0) {
        schemas(first: $first, skip: $skip) @fetchAll {
          id
          resolver
          revocable
          schema
        }
      }
    `);

    const variables = {
      first: options?.limit ?? 100,
      skip: options?.offset ?? 0,
    };

    const result = (await this.theGraph.client.request(query, variables)) as ResultOf<typeof query>;
    const list = (result as any).schemas as Array<{
      id: string;
      resolver: string;
      revocable: boolean;
      schema: string | null;
    }>;

    return list.map((s) => ({
      uid: s.id as Hex,
      resolver: s.resolver as Address,
      revocable: Boolean(s.revocable),
      schema: s.schema ?? "",
    }));
  }


/**
Expand Down Expand Up @@ -586,10 +630,72 @@ export class EASClient {
* as Portal's direct contract queries don't support listing all attestations.
* Consider using getAttestation() for individual attestation lookups.
*/
public async getAttestations(_options?: GetAttestationsOptions): Promise<AttestationInfo[]> {
throw new Error(
"Attestation listing not implemented yet. Portal's direct contract queries don't support listing all attestations. Use getAttestation() for individual attestation lookups or implement The Graph subgraph integration for bulk queries.",
);
public async getAttestations(options?: GetAttestationsOptions): Promise<AttestationInfo[]> {
if (!this.theGraph) {
throw new Error(
"Attestation listing requires The Graph configuration. Provide 'theGraph' options when creating EAS client.",
);
}

const query = this.theGraph.graphql(`
query ListAttestations($first: Int = 100, $skip: Int = 0, $schema: Bytes, $attester: Bytes, $recipient: Bytes) {
attestations(
first: $first
skip: $skip
where: {
${options?.schema ? "schema: $schema" : ""}
${options?.attester ? "attester: $attester" : ""}
${options?.recipient ? "recipient: $recipient" : ""}
}
) @fetchAll {
id
schema { id }
attester
recipient
time
expirationTime
revocable
refUID
data
revokedAt
}
}
`);

const variables: Record<string, unknown> = {
first: options?.limit ?? 100,
skip: options?.offset ?? 0,
};
if (options?.schema) variables.schema = options.schema;
if (options?.attester) variables.attester = options.attester;
if (options?.recipient) variables.recipient = options.recipient;

const result = (await this.theGraph.client.request(query, variables)) as ResultOf<typeof query>;
const list = (result as any).attestations as Array<{
id: string;
schema: { id: string } | string;
attester: string;
recipient: string;
time: string | number | null;
expirationTime: string | number | null;
revocable: boolean;
refUID: string | null;
data: string | null;
revokedAt?: string | null;
}>;

return list.map((a) => ({
uid: (a.id ?? (a as any).uid) as Hex,
schema: (typeof a.schema === "string" ? a.schema : a.schema.id) as Hex,
attester: a.attester as Address,
recipient: a.recipient as Address,
time: a.time ? BigInt(a.time) : BigInt(0),
expirationTime: a.expirationTime ? BigInt(a.expirationTime) : BigInt(0),
revocable: Boolean(a.revocable),
refUID: (a.refUID ?? ("0x" + "0".repeat(64))) as Hex,
data: (a.data ?? "0x") as Hex,
value: BigInt(0),
}));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The mapping logic for attestations includes defensive code that seems to contradict the GraphQL query and the subgraph schema. For instance:

  • (a.id ?? (a as any).uid): The schema defines id, so the fallback to uid is confusing and suggests uncertainty about the API response.
  • (typeof a.schema === "string" ? a.schema : a.schema.id): The query specifically requests schema { id }, so a.schema should always be an object, not a string.

This defensive coding makes the logic harder to follow and maintain. It should be simplified to align with the expected response shape defined by the GraphQL query.

    return list.map((a) => ({
      uid: a.id as Hex,
      schema: (a.schema as { id: string }).id as Hex,
      attester: a.attester as Address,
      recipient: a.recipient as Address,
      time: a.time ? BigInt(a.time) : BigInt(0),
      expirationTime: a.expirationTime ? BigInt(a.expirationTime) : BigInt(0),
      revocable: Boolean(a.revocable),
      refUID: (a.refUID ?? ("0x" + "0".repeat(64))) as Hex,
      data: (a.data ?? "0x") as Hex,
      value: BigInt(0),
    }));

}

/**
Expand Down
133 changes: 133 additions & 0 deletions sdk/eas/src/examples/the-graph-workflow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/**
* EAS The Graph Listing Example
*
* This example demonstrates how to configure the EAS SDK with The Graph
* and perform bulk reads for schemas and attestations using the same style
* as the other examples.
*/

import { createEASClient } from "../eas.js";
import { createLogger, requestLogger } from "@settlemint/sdk-utils/logging";
import { loadEnv } from "@settlemint/sdk-utils/environment";
import type { Address, Hex } from "viem";
import { decodeAbiParameters, parseAbiParameters } from "viem";

async function theGraphWorkflow() {
const logger = createLogger();
const env = await loadEnv(true, false);

if (!env.SETTLEMINT_PORTAL_GRAPHQL_ENDPOINT) {
console.error("❌ Missing SETTLEMINT_PORTAL_GRAPHQL_ENDPOINT");
process.exit(1);
}
if (!env.SETTLEMINT_THEGRAPH_SUBGRAPHS_ENDPOINTS || env.SETTLEMINT_THEGRAPH_SUBGRAPHS_ENDPOINTS.length === 0) {
console.error("❌ Missing SETTLEMINT_THEGRAPH_SUBGRAPHS_ENDPOINTS (JSON array of subgraph URLs ending with /<name>)");
process.exit(1);
}

console.log("🚀 EAS The Graph Listing Example");
console.log("================================\n");

// Build client with The Graph config
const eas = createEASClient(
{
instance: env.SETTLEMINT_PORTAL_GRAPHQL_ENDPOINT,
accessToken: env.SETTLEMINT_ACCESS_TOKEN,
theGraph: {
instances: env.SETTLEMINT_THEGRAPH_SUBGRAPHS_ENDPOINTS,
subgraphName: env.SETTLEMINT_THEGRAPH_DEFAULT_SUBGRAPH ?? "eas",
accessToken: env.SETTLEMINT_ACCESS_TOKEN,
cache: "force-cache",
},
debug: true,
},
);

// Replace global fetch logging for visibility (no-op in Node unless used)
// This pattern mirrors other examples and ensures consistent logging.
void requestLogger(logger, "eas-thegraph", fetch);

// Step 1: List Schemas
console.log("📚 Step 1: List Schemas (via The Graph)");
try {
const schemas = await eas.getSchemas({ limit: 10, offset: 0 });
if (schemas.length === 0) {
console.log("⚠️ No schemas found in the subgraph\n");
} else {
console.log(`✅ Found ${schemas.length} schema(s)`);
for (const s of schemas) {
console.log(` • ${s.uid} | revocable=${s.revocable} | resolver=${s.resolver}`);
}
console.log();
}
} catch (error) {
console.log("❌ Failed to list schemas:", error);
console.log();
}

// Step 2: List Attestations (optionally filter by schema/attester/recipient)
console.log("🧾 Step 2: List Attestations (via The Graph)");
try {
// Optional filters
const schemaUID = process.env.EAS_SCHEMA_UID as Hex | undefined;
const attester = process.env.EAS_ATTESTER as Address | undefined;
const recipient = (env.SETTLEMINT_DEPLOYER_ADDRESS as Address | undefined) ?? (process.env.EAS_RECIPIENT as Address | undefined);

const attestations = await eas.getAttestations({
limit: 10,
offset: 0,
schema: schemaUID,
attester,
recipient,
});

if (attestations.length === 0) {
console.log("⚠️ No attestations found with current filters\n");
} else {
console.log(`✅ Found ${attestations.length} attestation(s)`);
for (const a of attestations) {
console.log(` • uid=${a.uid} schema=${a.schema} attester=${a.attester} recipient=${a.recipient}`);
}
console.log();
}
} catch (error) {
console.log("❌ Failed to list attestations:", error);
console.log();
}

// Step 3: (Optional) Decode attestation data for the first attestation of the first schema
console.log("🔍 Step 3: Optional Data Decode Example");
try {
const schemas = await eas.getSchemas({ limit: 1, offset: 0 });
if (schemas.length === 0) {
console.log("ℹ️ Skipping decode: no schemas available\n");
return;
}

const schema = schemas[0];
const [example] = await eas.getAttestations({ limit: 1, offset: 0, schema: schema.uid });
if (!example || !example.data || example.data === ("0x" as Hex)) {
console.log("ℹ️ Skipping decode: no example attestation with data found\n");
return;
}

// Convert the EAS schema string (e.g., "uint256 score, address user") to ABI parameter format
const abiParams = parseAbiParameters(schema.schema);
const decoded = decodeAbiParameters(abiParams, example.data);

console.log("✅ Decoded example attestation data:");
console.log(decoded);
console.log();
} catch (error) {
console.log("⚠️ Decode step failed:", error);
console.log();
}

console.log("🎉 The Graph listing example complete\n");
}

if (typeof require !== "undefined" && require.main === module) {
theGraphWorkflow().catch(console.error);
}

export { theGraphWorkflow };
5 changes: 5 additions & 0 deletions sdk/eas/src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ export interface SchemaField {
*/
export type EASClientOptions = z.infer<typeof EASClientOptionsSchema>;

/**
* Narrow type for The Graph configuration inside EAS options
*/
export type EASTheGraphOptions = NonNullable<EASClientOptions["theGraph"]>;

/**
* Schema registration request
*/
Expand Down
19 changes: 18 additions & 1 deletion sdk/eas/src/utils/validation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ApplicationAccessTokenSchema, UrlSchema } from "@settlemint/sdk-utils/validation";
import { ApplicationAccessTokenSchema, UrlOrPathSchema, UrlSchema } from "@settlemint/sdk-utils/validation";
import { type Address, isAddress } from "viem";
import { z } from "zod";

Expand Down Expand Up @@ -31,4 +31,21 @@ export const EASClientOptionsSchema = z.object({
* Whether to enable debug mode
*/
debug: z.boolean().optional(),
/**
* Optional The Graph configuration for enabling bulk listing queries
*/
theGraph: z
.object({
/** TheGraph subgraph endpoints (must include an entry that ends with `/<subgraphName>`). */
instances: z.array(UrlOrPathSchema),
/** Subgraph name used to select the correct instance from `instances`. */
subgraphName: z.string(),
/** Optional access token for authenticated Graph endpoints. */
accessToken: ApplicationAccessTokenSchema.optional(),
/** Optional cache policy passed to GraphQL client. */
cache: z
.enum(["default", "force-cache", "no-cache", "no-store", "only-if-cached", "reload"])
.optional(),
})
.optional(),
});
6 changes: 6 additions & 0 deletions sdk/eas/subgraph/abis/EAS.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"abi": [
{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"uid","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"schema","type":"bytes32"},{"indexed":true,"internalType":"address","name":"attester","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint64","name":"time","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"expirationTime","type":"uint64"},{"indexed":false,"internalType":"bool","name":"revocable","type":"bool"},{"indexed":false,"internalType":"bytes32","name":"refUID","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"Attested","type":"event"},
{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"revoker","type":"address"},{"indexed":true,"internalType":"bytes32","name":"schema","type":"bytes32"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"bytes32","name":"uid","type":"bytes32"}],"name":"Revoked","type":"event"}
]
}
5 changes: 5 additions & 0 deletions sdk/eas/subgraph/abis/SchemaRegistry.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"abi": [
{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"uid","type":"bytes32"},{"indexed":true,"internalType":"address","name":"resolver","type":"address"},{"indexed":false,"internalType":"bool","name":"revocable","type":"bool"},{"indexed":false,"internalType":"string","name":"schema","type":"string"}],"name":"Registered","type":"event"}
]
}
24 changes: 24 additions & 0 deletions sdk/eas/subgraph/schema.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# EAS Subgraph Schema (MVP)

type Schema @entity {
id: Bytes! # uid
resolver: Bytes!
revocable: Boolean!
schema: String!
createdAt: BigInt!
txHash: Bytes!
}

type Attestation @entity {
id: Bytes! # uid
schema: Schema!
attester: Bytes!
recipient: Bytes!
time: BigInt!
expirationTime: BigInt!
revocable: Boolean!
refUID: Bytes!
data: Bytes!
revokedAt: BigInt
txHash: Bytes!
}
Loading
Loading