EFP Follow Graph
These queries read Ethereum Follow Protocol (EFP)
data, which requires the efp plugin
to be enabled on the connected ENSIndexer. It is enabled on the hosted ENSNode 'Alpha' instance.
This query loads an account's validated EFP social graph — its primary list, following, and followers — and resolves each followed account's ENS primary name. Requires the efp plugin.
query EfpFollowGraph($address: Address!) { account(by: { address: $address }) { efp { # The validated primary list, or null if unset/unvalidated. primaryList { tokenId } # following/followers are validated and block/mute-filtered, so the # edges are full Accounts you can walk straight into ENS names. following(first: 10) { totalCount edges { node { address resolve { primaryName(by: { chainName: ETHEREUM }) { name { beautified } } } } } } followers(first: 10) { totalCount edges { node { address } } } } }}{ "address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"}{ "data": { "account": { "efp": { "primaryList": { "tokenId": "6509" }, "following": { "totalCount": 10, "edges": [ { "node": { "address": "0x1b63142628311395ceafeea5667e7c9026c862ca", "resolve": { "primaryName": { "name": { "beautified": "tgerring.eth" } } } } }, { "node": { "address": "0x2b888954421b424c5d3d9ce9bb67c9bd47537d12", "resolve": { "primaryName": { "name": { "beautified": "lefteris.eth" } } } } }, { "node": { "address": "0x50ec05ade8280758e2077fcbc08d878d4aef79c3", "resolve": { "primaryName": { "name": { "beautified": "hayden.eth" } } } } }, { "node": { "address": "0x54becc7560a7be76d72ed76a1f5fee6c5a2a7ab6", "resolve": { "primaryName": { "name": { "beautified": "simona.eth" } } } } }, { "node": { "address": "0x5b76f5b8fc9d700624f78208132f91ad4e61a1f0", "resolve": { "primaryName": { "name": { "beautified": "barmstrong.eth" } } } } }, { "node": { "address": "0x648aa14e4424e0825a5ce739c8c68610e143fb79", "resolve": { "primaryName": { "name": { "beautified": "sassal.eth" } } } } }, { "node": { "address": "0x983110309620d911731ac0932219af06091b6744", "resolve": { "primaryName": { "name": { "beautified": "brantly.eth" } } } } }, { "node": { "address": "0xb8c2c29ee19d8307cb7255e1cd9cbde883a267d5", "resolve": { "primaryName": { "name": { "beautified": "nick.eth" } } } } }, { "node": { "address": "0xd7029bdea1c17493893aafe29aad69ef892b8ff2", "resolve": { "primaryName": { "name": null } } } }, { "node": { "address": "0xf56345338cb4cddaf915ebef3bfde63e70fe3053", "resolve": { "primaryName": { "name": { "beautified": "bored.eth" } } } } } ] }, "followers": { "edges": [ { "node": { "address": "0x00000066ced4c62a0f740de74eb08bc2a1552764" } }, { "node": { "address": "0x000000dcf1190af44f7149b85299f18ce7221024" } }, { "node": { "address": "0x000066b5a8e1e35b7e2f64e24715829647f80000" } }, { "node": { "address": "0x00076993122809055293d8210a60d8265a7e17f3" } }, { "node": { "address": "0x000f16ca1e73a0b6b10e1ed4cc5f8232336c1482" } }, { "node": { "address": "0x0011e9582ac18d9b80204817eaa2e3b544e727aa" } }, { "node": { "address": "0x00173c4cb23e6d876fcb036ba954a2f9cfcafa19" } }, { "node": { "address": "0x00197ff7abdac8ad42152ff9d5bd9e521701a944" } }, { "node": { "address": "0x002153708f11f2651215059eea30820ee4d49ff3" } }, { "node": { "address": "0x003e7b75ff09615ad4a6f763dc7d28e48ed513d9" } } ], "totalCount": 5338 } } } }}Output matches a point in time snapshot GraphQL response from our alpha ENSNode instance. Live output depends on the configuration of your ENSNode instance and ENS state updates.
import { createEnsNodeClient } from "enssdk/core";import { graphql, omnigraph } from "enssdk/omnigraph";
const client = createEnsNodeClient({ url: process.env.ENSNODE_URL || "https://api.alpha.ensnode.io"}).extend(omnigraph);
const EfpFollowGraphQuery = graphql(` query EfpFollowGraph($address: Address!) { account(by: { address: $address }) { efp { # The validated primary list, or null if unset/unvalidated. primaryList { tokenId } # following/followers are validated and block/mute-filtered, so the # edges are full Accounts you can walk straight into ENS names. following(first: 10) { totalCount edges { node { address resolve { primaryName(by: { chainName: ETHEREUM }) { name { beautified } } } } } } followers(first: 10) { totalCount edges { node { address } } } } } }`);
const result = await client.omnigraph.query({ query: EfpFollowGraphQuery, variables: { address: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", },});
if (result.errors) throw new Error(JSON.stringify(result.errors));console.log(JSON.stringify(result.data, null, 2));{ "data": { "account": { "efp": { "primaryList": { "tokenId": "6509" }, "following": { "totalCount": 10, "edges": [ { "node": { "address": "0x1b63142628311395ceafeea5667e7c9026c862ca", "resolve": { "primaryName": { "name": { "beautified": "tgerring.eth" } } } } }, { "node": { "address": "0x2b888954421b424c5d3d9ce9bb67c9bd47537d12", "resolve": { "primaryName": { "name": { "beautified": "lefteris.eth" } } } } }, { "node": { "address": "0x50ec05ade8280758e2077fcbc08d878d4aef79c3", "resolve": { "primaryName": { "name": { "beautified": "hayden.eth" } } } } }, { "node": { "address": "0x54becc7560a7be76d72ed76a1f5fee6c5a2a7ab6", "resolve": { "primaryName": { "name": { "beautified": "simona.eth" } } } } }, { "node": { "address": "0x5b76f5b8fc9d700624f78208132f91ad4e61a1f0", "resolve": { "primaryName": { "name": { "beautified": "barmstrong.eth" } } } } }, { "node": { "address": "0x648aa14e4424e0825a5ce739c8c68610e143fb79", "resolve": { "primaryName": { "name": { "beautified": "sassal.eth" } } } } }, { "node": { "address": "0x983110309620d911731ac0932219af06091b6744", "resolve": { "primaryName": { "name": { "beautified": "brantly.eth" } } } } }, { "node": { "address": "0xb8c2c29ee19d8307cb7255e1cd9cbde883a267d5", "resolve": { "primaryName": { "name": { "beautified": "nick.eth" } } } } }, { "node": { "address": "0xd7029bdea1c17493893aafe29aad69ef892b8ff2", "resolve": { "primaryName": { "name": null } } } }, { "node": { "address": "0xf56345338cb4cddaf915ebef3bfde63e70fe3053", "resolve": { "primaryName": { "name": { "beautified": "bored.eth" } } } } } ] }, "followers": { "edges": [ { "node": { "address": "0x00000066ced4c62a0f740de74eb08bc2a1552764" } }, { "node": { "address": "0x000000dcf1190af44f7149b85299f18ce7221024" } }, { "node": { "address": "0x000066b5a8e1e35b7e2f64e24715829647f80000" } }, { "node": { "address": "0x00076993122809055293d8210a60d8265a7e17f3" } }, { "node": { "address": "0x000f16ca1e73a0b6b10e1ed4cc5f8232336c1482" } }, { "node": { "address": "0x0011e9582ac18d9b80204817eaa2e3b544e727aa" } }, { "node": { "address": "0x00173c4cb23e6d876fcb036ba954a2f9cfcafa19" } }, { "node": { "address": "0x00197ff7abdac8ad42152ff9d5bd9e521701a944" } }, { "node": { "address": "0x002153708f11f2651215059eea30820ee4d49ff3" } }, { "node": { "address": "0x003e7b75ff09615ad4a6f763dc7d28e48ed513d9" } } ], "totalCount": 5338 } } } }}Output matches a point in time snapshot GraphQL response from our alpha ENSNode instance. Live output depends on the configuration of your ENSNode instance and ENS state updates.
enssdk package manager setup
# 1. Create projectmkdir -p my-ens-script/src && cd my-ens-scriptnpm init -y && touch src/index.tsnpm pkg set type=module scripts.start="tsx src/index.ts"# 2. Install dependenciesnpm install enssdk@1.16.0 && npm install -D tsx typescript @types/node# 3. Paste the TypeScript snippet above into src/index.ts# 4. RunENSNODE_URL=https://api.alpha.ensnode.io npm startSee the enssdk docs for gql.tada plugin and tsconfig setup.
import { OmnigraphProvider, useOmnigraphQuery, graphql } from "enskit/react/omnigraph";import { createEnsNodeClient } from "enssdk/core";import { omnigraph } from "enssdk/omnigraph";
const client = createEnsNodeClient({ url: import.meta.env.VITE_ENSNODE_URL || "https://api.alpha.ensnode.io"}).extend(omnigraph);
const EfpFollowGraphQuery = graphql(` query EfpFollowGraph($address: Address!) { account(by: { address: $address }) { efp { # The validated primary list, or null if unset/unvalidated. primaryList { tokenId } # following/followers are validated and block/mute-filtered, so the # edges are full Accounts you can walk straight into ENS names. following(first: 10) { totalCount edges { node { address resolve { primaryName(by: { chainName: ETHEREUM }) { name { beautified } } } } } } followers(first: 10) { totalCount edges { node { address } } } } } }`);
function EfpFollowGraphResult() { const [result] = useOmnigraphQuery({ query: EfpFollowGraphQuery, variables: { address: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", }, }); const { data, fetching, error } = result; if (!data && fetching) return <p>Loading…</p>; if (error) return <p>Error: {error.message}</p>; if (!data) return <p>No data returned.</p>; const formatted = JSON.stringify( data, (_, value) => (typeof value === "bigint" ? value.toString() : value), 2, ); return <code>{formatted}</code>;}
export default function App() { return ( <OmnigraphProvider client={client}> <EfpFollowGraphResult /> </OmnigraphProvider> );}{ "data": { "account": { "efp": { "primaryList": { "tokenId": "6509" }, "following": { "totalCount": 10, "edges": [ { "node": { "address": "0x1b63142628311395ceafeea5667e7c9026c862ca", "resolve": { "primaryName": { "name": { "beautified": "tgerring.eth" } } } } }, { "node": { "address": "0x2b888954421b424c5d3d9ce9bb67c9bd47537d12", "resolve": { "primaryName": { "name": { "beautified": "lefteris.eth" } } } } }, { "node": { "address": "0x50ec05ade8280758e2077fcbc08d878d4aef79c3", "resolve": { "primaryName": { "name": { "beautified": "hayden.eth" } } } } }, { "node": { "address": "0x54becc7560a7be76d72ed76a1f5fee6c5a2a7ab6", "resolve": { "primaryName": { "name": { "beautified": "simona.eth" } } } } }, { "node": { "address": "0x5b76f5b8fc9d700624f78208132f91ad4e61a1f0", "resolve": { "primaryName": { "name": { "beautified": "barmstrong.eth" } } } } }, { "node": { "address": "0x648aa14e4424e0825a5ce739c8c68610e143fb79", "resolve": { "primaryName": { "name": { "beautified": "sassal.eth" } } } } }, { "node": { "address": "0x983110309620d911731ac0932219af06091b6744", "resolve": { "primaryName": { "name": { "beautified": "brantly.eth" } } } } }, { "node": { "address": "0xb8c2c29ee19d8307cb7255e1cd9cbde883a267d5", "resolve": { "primaryName": { "name": { "beautified": "nick.eth" } } } } }, { "node": { "address": "0xd7029bdea1c17493893aafe29aad69ef892b8ff2", "resolve": { "primaryName": { "name": null } } } }, { "node": { "address": "0xf56345338cb4cddaf915ebef3bfde63e70fe3053", "resolve": { "primaryName": { "name": { "beautified": "bored.eth" } } } } } ] }, "followers": { "edges": [ { "node": { "address": "0x00000066ced4c62a0f740de74eb08bc2a1552764" } }, { "node": { "address": "0x000000dcf1190af44f7149b85299f18ce7221024" } }, { "node": { "address": "0x000066b5a8e1e35b7e2f64e24715829647f80000" } }, { "node": { "address": "0x00076993122809055293d8210a60d8265a7e17f3" } }, { "node": { "address": "0x000f16ca1e73a0b6b10e1ed4cc5f8232336c1482" } }, { "node": { "address": "0x0011e9582ac18d9b80204817eaa2e3b544e727aa" } }, { "node": { "address": "0x00173c4cb23e6d876fcb036ba954a2f9cfcafa19" } }, { "node": { "address": "0x00197ff7abdac8ad42152ff9d5bd9e521701a944" } }, { "node": { "address": "0x002153708f11f2651215059eea30820ee4d49ff3" } }, { "node": { "address": "0x003e7b75ff09615ad4a6f763dc7d28e48ed513d9" } } ], "totalCount": 5338 } } } }}Output matches a point in time snapshot GraphQL response from our alpha ENSNode instance. Live output depends on the configuration of your ENSNode instance and ENS state updates.
enskit package manager setup
# 1. Create projectnpm create vite@latest my-ens-app -- --template react-ts --no-interactive --no-immediatecd my-ens-app# 2. Install dependenciesnpm installnpm install enskit@1.16.0 enssdk@1.16.0# 3. Copy the TSX snippet above into src/App.tsx# 4. RunVITE_ENSNODE_URL=https://api.alpha.ensnode.io npm run devSee the enskit docs for gql.tada plugin and provider setup.
# POST JSON to your ENSNode Omnigraph endpoint (same path enssdk uses).curl -sS -X POST "https://api.alpha.ensnode.io/api/omnigraph" \ -H "Content-Type: application/json" \ -d '{ "query": "query EfpFollowGraph($address: Address!) { account(by: { address: $address }) { efp { primaryList { tokenId } following(first: 10) { totalCount edges { node { address resolve { primaryName(by: { chainName: ETHEREUM }) { name { beautified } } } } } } followers(first: 10) { totalCount edges { node { address } } } } } }", "variables": {"address":"0xd8da6bf26964af9d7eed9e03e53415d37aa96045"}}'{ "data": { "account": { "efp": { "primaryList": { "tokenId": "6509" }, "following": { "totalCount": 10, "edges": [ { "node": { "address": "0x1b63142628311395ceafeea5667e7c9026c862ca", "resolve": { "primaryName": { "name": { "beautified": "tgerring.eth" } } } } }, { "node": { "address": "0x2b888954421b424c5d3d9ce9bb67c9bd47537d12", "resolve": { "primaryName": { "name": { "beautified": "lefteris.eth" } } } } }, { "node": { "address": "0x50ec05ade8280758e2077fcbc08d878d4aef79c3", "resolve": { "primaryName": { "name": { "beautified": "hayden.eth" } } } } }, { "node": { "address": "0x54becc7560a7be76d72ed76a1f5fee6c5a2a7ab6", "resolve": { "primaryName": { "name": { "beautified": "simona.eth" } } } } }, { "node": { "address": "0x5b76f5b8fc9d700624f78208132f91ad4e61a1f0", "resolve": { "primaryName": { "name": { "beautified": "barmstrong.eth" } } } } }, { "node": { "address": "0x648aa14e4424e0825a5ce739c8c68610e143fb79", "resolve": { "primaryName": { "name": { "beautified": "sassal.eth" } } } } }, { "node": { "address": "0x983110309620d911731ac0932219af06091b6744", "resolve": { "primaryName": { "name": { "beautified": "brantly.eth" } } } } }, { "node": { "address": "0xb8c2c29ee19d8307cb7255e1cd9cbde883a267d5", "resolve": { "primaryName": { "name": { "beautified": "nick.eth" } } } } }, { "node": { "address": "0xd7029bdea1c17493893aafe29aad69ef892b8ff2", "resolve": { "primaryName": { "name": null } } } }, { "node": { "address": "0xf56345338cb4cddaf915ebef3bfde63e70fe3053", "resolve": { "primaryName": { "name": { "beautified": "bored.eth" } } } } } ] }, "followers": { "edges": [ { "node": { "address": "0x00000066ced4c62a0f740de74eb08bc2a1552764" } }, { "node": { "address": "0x000000dcf1190af44f7149b85299f18ce7221024" } }, { "node": { "address": "0x000066b5a8e1e35b7e2f64e24715829647f80000" } }, { "node": { "address": "0x00076993122809055293d8210a60d8265a7e17f3" } }, { "node": { "address": "0x000f16ca1e73a0b6b10e1ed4cc5f8232336c1482" } }, { "node": { "address": "0x0011e9582ac18d9b80204817eaa2e3b544e727aa" } }, { "node": { "address": "0x00173c4cb23e6d876fcb036ba954a2f9cfcafa19" } }, { "node": { "address": "0x00197ff7abdac8ad42152ff9d5bd9e521701a944" } }, { "node": { "address": "0x002153708f11f2651215059eea30820ee4d49ff3" } }, { "node": { "address": "0x003e7b75ff09615ad4a6f763dc7d28e48ed513d9" } } ], "totalCount": 5338 } } } }}Output matches a point in time snapshot GraphQL response from our alpha ENSNode instance. Live output depends on the configuration of your ENSNode instance and ENS state updates.
Back to Examples