Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ export const integrateSidebarTopic = {
label: "Protocol Acceleration",
link: "/docs/integrate/omnigraph/protocol-acceleration",
},
{
label: "EFP",
link: "/docs/integrate/omnigraph/efp",
},
{
label: "FAQ",
link: "/docs/integrate/omnigraph/faq",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
// Renders a plugin-requirement Aside for an Omnigraph example, driven by the example's category.
// Example pages pass their `id`; the component looks the example up and renders the matching aside
// (or nothing) so requirement notices stay consistent and live next to the example definition.
import { Aside } from "@astrojs/starlight/components";

import { getOmnigraphExampleConfigById } from "@data/omnigraph-examples/config";

interface Props {
id: string;
}

const { id } = Astro.props;
const category = getOmnigraphExampleConfigById(id)?.category;
---

{
category === "EFP" && (
Comment thread
shrugs marked this conversation as resolved.
Comment on lines +14 to +18
<Aside type="tip" title="EFP plugin required">
<p>
These queries read{" "}
<a href="/docs/integrate/omnigraph/efp">Ethereum Follow Protocol (EFP)</a> data, which
requires the{" "}
<a href="/docs/integrate/omnigraph/efp">
<code>efp</code> plugin
</a>{" "}
to be enabled on the connected ENSIndexer. It is enabled on the hosted{" "}
<a href="/docs/hosted-instances#ensnode-alpha">ENSNode 'Alpha'</a> instance.
</p>
</Aside>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import StaticExampleCard from "@components/molecules/omnigraph-static-example/St
import CurlStaticCodeExample from "@components/molecules/omnigraph-static-example/CurlStaticCodeExample.astro";
import SdkStaticCodeExample from "@components/molecules/omnigraph-static-example/SdkStaticCodeExample.astro";
import GraphqlStaticQueryExample from "@components/molecules/omnigraph-static-example/GraphqlStaticQueryExample.astro";
import ExampleRequirementAside from "@components/molecules/omnigraph-static-example/ExampleRequirementAside.astro";
import { exampleTabClass } from "@components/molecules/omnigraph-static-example/constants";
import { resolveOmnigraphStaticExample } from "@lib/examples/omnigraph/resolve-static-example";

Expand Down Expand Up @@ -37,6 +38,8 @@ const { description } = getOmnigraphExampleById(id);
const data = resolveOmnigraphStaticExample(id);
---

<ExampleRequirementAside id={id} />

{
!hideDescription && (
<div class="sl-markdown-content">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ These ENSNode instances do not constrain themselves to exclusively activating th
connectWithENSAdminURL="https://admin.ensnode.io/connection?connection=https%3A%2F%2Fapi.alpha.ensnode.io"
namespace="mainnet"
ensVersions="ENSv1 only (not also ENSv2 yet)"
plugins={`${pluginLink("unigraph")}, ${pluginLink("protocol-acceleration")}, ${pluginLink("subgraph")}, ${pluginLink("basenames")}, ${pluginLink("lineanames")}, ${pluginLink("threedns")}, ${pluginLink("registrars")}, ${pluginLink("tokenscope")}`}
plugins={`${pluginLink("unigraph")}, ${pluginLink("protocol-acceleration")}, ${pluginLink("subgraph")}, ${pluginLink("basenames")}, ${pluginLink("lineanames")}, ${pluginLink("threedns")}, ${pluginLink("registrars")}, ${pluginLink("tokenscope")}, ${pluginLink("efp")}`}
>
<Fragment slot="ens-omnigraph-api-icon" set:text={"✅"} />
<Fragment slot="ens-omnigraph-api" set:html={omnigraphForEnsV1} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,20 @@ When new ENSNode plugins are created, it becomes possible for the [ENS Omnigraph

[ENSIndexer](/docs/services/ensindexer) is a reference implementation of an [ENSDb Writer](/docs/services/ensdb/concepts/glossary#ensdb-writer) that implements multiple existing ENSNode Plugin specifications. The code for each plugin inside ENSIndexer is a reference implementation of that plugin's abstract specification. [The ENSNode Plugins implemented in ENSIndexer today](https://github.com/namehash/ensnode/tree/main/apps/ensindexer/src/plugins) are:

| Plugin | Description |
| ----------------------- | ---------------------------------------------------------- |
| `unigraph` | Unified ENSv1 + ENSv2 data model with polymorphic entities |
| `protocol-acceleration` | Accelerated lookups for ENS resolution |
| `subgraph` | Legacy ENS Subgraph-compatible data model |
| `basenames` | Basenames (`.base.eth`) subname indexing |
| `lineanames` | Lineanames (`.linea.eth`) subname indexing |
| `threedns` | 3DNS (`.box`) name indexing |
| `registrars` | Registration and renewal lifecycle tracking |
| `tokenscope` | NFT tokenization of ENS names |
| Plugin | Description |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `unigraph` | Unified ENSv1 + ENSv2 data model with polymorphic entities |
| `protocol-acceleration` | Accelerated lookups for ENS resolution |
| `subgraph` | Legacy ENS Subgraph-compatible data model |
| `basenames` | Basenames (`.base.eth`) subname indexing |
| `lineanames` | Lineanames (`.linea.eth`) subname indexing |
| `threedns` | 3DNS (`.box`) name indexing |
| `registrars` | Registration and renewal lifecycle tracking |
| `tokenscope` | NFT tokenization of ENS names |
| `efp` | [Ethereum Follow Protocol](https://efp.app/) onchain social graph (lists, records, tags) — see [EFP in the Omnigraph](/docs/integrate/omnigraph/efp) |

## New Plugins

### Under Development

An `efp` plugin for the [Ethereum Follow Protocol](https://efp.app/) is [already under active development](https://github.com/Quantumlyy/efpnode/tree/main/packages/ensnode-plugin-efp) by the [EthId team](https://ethid.org/).

### Build Your Own

If you are interested in defining a new ENSNode plugin or implementing an existing one, reach out to the NameHash Labs team — we are happy to provide support and additional info. Join us on [Telegram](https://t.me/ensnode) for any questions.
Expand Down
62 changes: 62 additions & 0 deletions docs/ensnode.io/src/content/docs/docs/integrate/omnigraph/efp.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
title: Ethereum Follow Protocol (EFP)
description: Query the Ethereum Follow Protocol (EFP) onchain social graph through the ENS Omnigraph API by enabling the efp plugin.
sidebar:
label: EFP
---

import { LinkCard } from "@astrojs/starlight/components";
import OmnigraphStaticExampleSet from "@components/organisms/OmnigraphStaticExampleSet.astro";

The [Ethereum Follow Protocol (EFP)](https://efp.app) is an onchain social graph for Ethereum accounts — a decentralized "who follows whom" primitive. Because EFP composes directly with ENS identity, the ENS Omnigraph API exposes it alongside ENS data, so you can read an account's follow graph **and** resolve each followed account's ENS name in a single query.

## Enabling the plugin

EFP is indexed by the **`efp` plugin**. The Omnigraph's `Query.efp` and `Account.efp` fields return data only when the connected ENSIndexer has this plugin enabled; otherwise they resolve to `null` — treat that like any other unsupported-instance case, not a query error.

To enable it on your own instance, add `efp` to the ENSIndexer `PLUGINS` environment variable (a comma-separated list), for example:

```bash
PLUGINS=unigraph,efp
```

The `efp` plugin's datasources are defined for the **mainnet** namespace (the EFP contracts on Base, OP Mainnet, and Ethereum Mainnet) and the local **ens-test-env** devnet.

:::note[Already enabled on the Alpha instance]
The hosted [ENSNode 'Alpha'](/docs/hosted-instances#ensnode-alpha) instance has the `efp` plugin enabled, so you can run every query on this page against it without hosting anything yourself.
:::

## What it indexes

The plugin indexes the full EFP onchain state into ENSDb:

- **Lists** — the ERC-721 NFTs that hold follow relationships, with their `owner` / `manager` / `user` roles and storage location.
- **List records** — the individual follows (address records), each with its **tags** (`block`, `mute`, `top8`, and custom tags).
- **Account metadata** — the onchain `(address, key) → value` store, including the `primary-list` key used to validate an account's primary list.

## The API surface

EFP is exposed through two entry points:

- **`Account.efp`** — an account's EFP presence: validated, block/mute-filtered `following` / `followers` connections (whose edges are full `Account`s you can resolve straight into ENS names), the validated `primaryList`, and raw account `metadata`.
- **`Query.efp`** — list-centric queries: `list(by: { tokenId })`, `lists(where:)` by role address, and `listRecords(where:)` (the raw record set, including `block`/`mute`).

Prefer `Account.efp.following` / `followers` for the social-graph answer — they apply EFP's primary-list validation and block/mute filtering for you. Drop to the raw `Query.efp.listRecords` / `EfpList.records` only when you specifically need tags, storage location, or non-primary lists.

## Example

<OmnigraphStaticExampleSet id="efp-follow-graph" hideBackToExamples />

## Learn more

<LinkCard
title="EFP examples"
description="Runnable Omnigraph queries for the EFP social graph, lists, and records."
href="/docs/integrate/omnigraph/examples"
/>

<LinkCard
title="EFP protocol docs"
description="The data model and validity rules behind EFP, at docs.efp.app."
href="https://docs.efp.app"
/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: EFP Follow Graph
---

import OmnigraphStaticExampleSet from "@components/organisms/OmnigraphStaticExampleSet.astro";

<OmnigraphStaticExampleSet id="efp-follow-graph" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: EFP List
---

import OmnigraphStaticExampleSet from "@components/organisms/OmnigraphStaticExampleSet.astro";

<OmnigraphStaticExampleSet id="efp-list" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: EFP Who Follows
---

import OmnigraphStaticExampleSet from "@components/organisms/OmnigraphStaticExampleSet.astro";

<OmnigraphStaticExampleSet id="efp-who-follows" />
Loading
Loading