Using Index Supply as the Indexer
The Ethereum Comments Protocol can be integrated with Index Supply as an alternative indexing solution. This guide will walk you through the steps to setup Index Supply to query comments from the protocol.
Event Signatures
All events emitted by the CommentManager
contract can be found here.
Struct to Tuple Conversion
Index Supply does not recognize struct
in event signatures.
all struct
s must be converted into a tuple
according to
Human Readable ABI format.
For example, the CommentAdded
event was defined as:
event CommentAdded(
bytes32 indexed commentId,
address indexed author,
address indexed app,
CommentData commentData
);
It must be converted to the following tuple form in order to work with Index Supply:
CommentAdded(bytes32 indexed commentId, address indexed author, address indexed app, (string content, string metadata, string targetUri, bytes32 parentId, address author, address app, bytes32 salt, uint256 deadline) commentData)
please note: at the time of writing, Index Supply's query interface doesn't support multi-line event signatures.
Dependencies
All examples below requires installing the following dependencies:
npm install @ecp.eth/sdk zod
Fetching Comments
We will build a fetchComments()
function to fetch comments for a given URI via Index Supply.
Create Index Supply Client
Create a simple client wrapper for Index Supply:
export type ISPrimitive = string | number | boolean | null;
export type ISRow = ISPrimitive[];
export type ISRows = ISRow[];
export type ISResponse = {
block_height: number;
result: [[string[], ...ISRows]];
};
export const indexSupplyClient = {
async query(chain: string, query: string, eventSignatures: string[]) {
const params = new URLSearchParams({
chain,
query,
event_signatures: eventSignatures.join(","),
});
const response = await fetch(
`https://api.indexsupply.net/query?${params.toString()}`
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json() as Promise<ISResponse>;
},
};
Fetch Comments function for a URI
Here's how to fetch comments for a specific URI using Index Supply:
import { z } from "zod";
import { COMMENT_MANAGER_ADDRESS } from "@ecp.eth/sdk";
import { HexSchema } from "@ecp.eth/sdk/core";
import { indexSupplyClient, ISPrimitive } from "./isClient";
const COMMENT_ADDED_EVENT = `CommentAdded(
bytes32 indexed commentId,
address indexed author,
address indexed app,
(
string content,
string metadata,
string targetUri,
bytes32 parentId,
address author,
address app,
bytes32 salt,
uint256 deadline
) commentData
)`;
const commentSchema = z.object({
id: z.string(),
content: z.string(),
targetUri: z.string(),
author: HexSchema,
app: HexSchema,
parentId: z.string().nullable(),
blockNumber: z.number(),
transactionHash: HexSchema,
});
type Comment = z.infer<typeof commentSchema>;
async function fetchComments(
targetUri: string,
app: string,
chain = "8453"
): Promise<Comment[]> {
const query = `
SELECT
commentId as "id",
(commentData->>'content') as "content",
(commentData->>'targetUri') as "targetUri",
"author",
"app",
(commentData->>'parentId') as "parentId",
block_num as "blockNumber",
tx_hash as "transactionHash"
FROM
CommentAdded
WHERE
address = ${COMMENT_MANAGER_ADDRESS}
AND
app = ${app}
AND
commentData->>'targetUri' = '${targetUri}'
ORDER BY block_num DESC
LIMIT 10
`;
try {
const response = await indexSupplyClient.query(chain, query, [
COMMENT_ADDED_EVENT,
]);
if (!response.result?.[0]) {
return [];
}
const [columns, ...rows] = response.result[0];
if (!columns) {
return [];
}
return rows
.map<Record<string, ISPrimitive>>((row: ISPrimitive[]) => {
return row.reduce<Record<string, ISPrimitive>>(
(record, value: ISPrimitive, index: number) => {
if (!columns[index]) {
return record;
}
record[columns[index]] = value;
return record;
},
{} as Record<string, ISPrimitive>
);
})
.filter((maybeComment): maybeComment is Comment => {
const result = commentSchema.safeParse(maybeComment);
if (!result.success) {
console.warn("Invalid comment", result.error);
}
return result.success;
});
} catch (error) {
console.error("Error fetching comments:", error);
throw error;
}
}
Run it
import { fetchComments } from "./fetchComments";
console.log(
await fetchComments(
"https://demo.ethcomments.xyz/",
"0xe86a6df8ead873600050fb669e7bc8d3b8587f3d"
)
);
Done
Limitations and Considerations
- Index Supply requires proper query optimization for best performance
- Consider using pagination for large result sets
- Add appropriate error handling for API rate limits and network issues
- The free tier has limitations on query complexity and frequency