// Operations for managing blockchain events
import { z } from "zod";
import { getEventsApi, getEventQueriesApi } from "../common/client";
import {
CurvegridResourceNotFoundError,
CurvegridError,
} from "../common/errors";
// Schema for listing events
export const ListEventsSchema = z.object({
address: z.string().describe("Contract address"),
eventName: z.string().describe("Event name"),
fromBlock: z.number().optional().describe("Starting block number"),
toBlock: z.number().optional().describe("Ending block number"),
limit: z.number().optional().describe("Maximum number of events to return"),
offset: z.number().optional().describe("Offset for pagination"),
});
// Schema for getting event count
export const GetEventCountSchema = z.object({
address: z.string().describe("Contract address"),
eventName: z.string().describe("Event name"),
fromBlock: z.number().optional().describe("Starting block number"),
toBlock: z.number().optional().describe("Ending block number"),
});
// Schema for event query filter
export const EventQueryFilterSchema: z.ZodType<any> = z.object({
rule: z.enum(["and", "or"]).optional().describe("Filter rule"),
fieldType: z
.enum(["input", "contract_label", "contract_name"])
.optional()
.describe("Field type"),
inputIndex: z.number().optional().describe("Field index"),
operator: z
.enum([
"equal",
"notequal",
"lessthan",
"greaterthan",
"lessthanorequal",
"greaterthanorequal",
])
.optional()
.describe("Filter operator"),
value: z.string().optional().describe("Filter value"),
children: z
.array(z.lazy((): z.ZodType<any> => EventQueryFilterSchema))
.optional()
.describe("Nested filters"),
});
// Schema for creating an event query
export const CreateEventQuerySchema = z.object({
name: z.string().describe("Name for the event query"),
events: z
.array(
z.object({
eventName: z.string().describe("Event name"),
select: z
.array(
z.object({
type: z
.enum(["input", "contract_label", "contract_name"])
.describe("Field type"),
name: z.string().optional().describe("Field name"),
inputIndex: z.number().optional().describe("Field index"),
alias: z.string().optional().describe("Field alias"),
aggregator: z
.enum(["add", "subtract", "last", "first", "min", "max"])
.optional()
.describe("Aggregation type"),
}),
)
.describe("Fields to select"),
filter: z
.object({
rule: z.enum(["and", "or"]).optional().describe("Filter rule"),
fieldType: z
.enum(["input", "contract_label", "contract_name"])
.optional()
.describe("Field type"),
inputIndex: z.number().optional().describe("Field index"),
operator: z
.enum([
"equal",
"notequal",
"lessthan",
"greaterthan",
"lessthanorequal",
"greaterthanorequal",
])
.optional()
.describe("Filter operator"),
value: z.string().optional().describe("Filter value"),
children: z
.array(z.lazy(() => EventQueryFilterSchema))
.optional()
.describe("Nested filters"),
})
.optional()
.describe("Filter conditions"),
}),
)
.describe("Events to query"),
groupBy: z.string().optional().describe("Field to group by"),
orderBy: z.string().optional().describe("Field to order by"),
order: z.enum(["ASC", "DESC"]).optional().describe("Sort order"),
});
// Schema for getting event query results
export const GetEventQueryResultsSchema = z.object({
queryName: z.string().describe("Name of the event query"),
limit: z.number().optional().describe("Maximum number of events to return"),
offset: z.number().optional().describe("Offset for pagination"),
});
// Schema for arbitrary event query
export const ArbitraryEventQuerySchema = z.object({
events: z
.array(
z.object({
eventName: z.string().describe("Event name"),
select: z
.array(
z.object({
type: z
.enum(["input", "contract_label", "contract_name"])
.describe("Field type"),
name: z.string().optional().describe("Field name"),
inputIndex: z.number().optional().describe("Field index"),
alias: z.string().optional().describe("Field alias"),
aggregator: z
.enum(["add", "subtract", "last", "first", "min", "max"])
.optional()
.describe("Aggregation type"),
}),
)
.describe("Fields to select"),
filter: z
.object({
rule: z.enum(["and", "or"]).optional().describe("Filter rule"),
fieldType: z
.enum(["input", "contract_label", "contract_name"])
.optional()
.describe("Field type"),
inputIndex: z.number().optional().describe("Field index"),
operator: z
.enum([
"equal",
"notequal",
"lessthan",
"greaterthan",
"lessthanorequal",
"greaterthanorequal",
])
.optional()
.describe("Filter operator"),
value: z.string().optional().describe("Filter value"),
children: z
.array(z.lazy(() => EventQueryFilterSchema))
.optional()
.describe("Nested filters"),
})
.optional()
.describe("Filter conditions"),
}),
)
.describe("Events to query"),
groupBy: z.string().optional().describe("Field to group by"),
orderBy: z.string().optional().describe("Field to order by"),
order: z.enum(["ASC", "DESC"]).optional().describe("Sort order"),
limit: z.number().optional().describe("Maximum number of events to return"),
offset: z.number().optional().describe("Offset for pagination"),
});
// Schema for getting event query details
export const GetEventQuerySchema = z.object({
name: z.string().describe("Name of the event query"),
});
// Schema for deleting event query
export const DeleteEventQuerySchema = z.object({
name: z.string().describe("Name of the event query to delete"),
});
// Schema for counting event query records
export const CountEventQueryRecordsSchema = z.object({
name: z.string().describe("Name of the event query"),
});
// Schema for listing event queries
export const ListEventQueriesSchema = z
.object({})
.describe("No parameters needed");
// List events for a contract
export async function listEvents(options: z.infer<typeof ListEventsSchema>) {
try {
const eventsApi = getEventsApi();
const response = await eventsApi.listEvents(
undefined, // blockHash
options.fromBlock, // blockNumber
undefined, // txIndexInBlock
undefined, // eventIndexInLog
undefined, // txHash
undefined, // fromConstructor
options.address, // contractAddress
undefined, // contractLabel
options.eventName, // eventSignature
options.limit,
options.offset,
);
return response.data;
} catch (error: any) {
if (error.response?.status === 404) {
throw new CurvegridResourceNotFoundError(
`Events for contract ${options.address} and event ${options.eventName} not found`,
);
}
throw new CurvegridError(`Failed to list events: ${error.message}`);
}
}
// Create an event query
export async function createEventQuery(
options: z.infer<typeof CreateEventQuerySchema>,
) {
try {
const eventQueriesApi = getEventQueriesApi();
const response = await eventQueriesApi.setEventQuery(options.name, {
events: options.events,
groupBy: options.groupBy,
orderBy: options.orderBy,
order: options.order,
});
return response.data;
} catch (error: any) {
throw new CurvegridError(`Failed to create event query: ${error.message}`);
}
}
// Get event query results
export async function getEventQueryResults(
options: z.infer<typeof GetEventQueryResultsSchema>,
) {
try {
const eventQueriesApi = getEventQueriesApi();
const response = await eventQueriesApi.executeEventQuery(
options.queryName,
options.offset,
options.limit,
);
return response.data;
} catch (error: any) {
if (error.response?.status === 404) {
throw new CurvegridResourceNotFoundError(
`Event query "${options.queryName}" not found`,
);
}
throw new CurvegridError(
`Failed to get event query results: ${error.message}`,
);
}
}
// Get event count
export async function getEventCount(
options: z.infer<typeof GetEventCountSchema>,
) {
try {
const eventsApi = getEventsApi();
const response = await eventsApi.getEventCount(
undefined, // blockHash
options.fromBlock, // blockNumber
undefined, // txIndexInBlock
undefined, // eventIndexInLog
undefined, // txHash
undefined, // fromConstructor
options.address, // contractAddress
undefined, // contractLabel
options.eventName, // eventSignature
);
return response.data.result;
} catch (error: any) {
if (error.response?.status === 404) {
throw new CurvegridResourceNotFoundError(
`Events for contract ${options.address} and event ${options.eventName} not found`,
);
}
throw new CurvegridError(`Failed to get event count: ${error.message}`);
}
}
// Execute arbitrary event query
export async function executeArbitraryEventQuery(
options: z.infer<typeof ArbitraryEventQuerySchema>,
) {
try {
const eventQueriesApi = getEventQueriesApi();
const response = await eventQueriesApi.executeArbitraryEventQuery(
{
events: options.events,
groupBy: options.groupBy,
orderBy: options.orderBy,
order: options.order,
},
options.offset,
options.limit,
);
return response.data;
} catch (error: any) {
throw new CurvegridError(
`Failed to execute arbitrary event query: ${error.message}`,
);
}
}
// List event queries
export async function listEventQueries() {
try {
const eventQueriesApi = getEventQueriesApi();
const response = await eventQueriesApi.listEventQueries();
return response.data.result;
} catch (error: any) {
throw new CurvegridError(`Failed to list event queries: ${error.message}`);
}
}
// Get event query details
export async function getEventQuery(
options: z.infer<typeof GetEventQuerySchema>,
) {
try {
const eventQueriesApi = getEventQueriesApi();
const response = await eventQueriesApi.getEventQuery(options.name);
return response.data.result;
} catch (error: any) {
if (error.response?.status === 404) {
throw new CurvegridResourceNotFoundError(
`Event query "${options.name}" not found`,
);
}
throw new CurvegridError(`Failed to get event query: ${error.message}`);
}
}
// Delete event query
export async function deleteEventQuery(
options: z.infer<typeof DeleteEventQuerySchema>,
) {
try {
const eventQueriesApi = getEventQueriesApi();
await eventQueriesApi.deleteEventQuery(options.name);
// Return true to indicate success (deleteEventQuery returns BaseResponse which has no result)
return true;
} catch (error: any) {
if (error.response?.status === 404) {
throw new CurvegridResourceNotFoundError(
`Event query "${options.name}" not found`,
);
}
throw new CurvegridError(`Failed to delete event query: ${error.message}`);
}
}
// Count event query records
export async function countEventQueryRecords(
options: z.infer<typeof CountEventQueryRecordsSchema>,
) {
try {
const eventQueriesApi = getEventQueriesApi();
const response = await eventQueriesApi.countEventQueryRecords(options.name);
return response.data.result;
} catch (error: any) {
if (error.response?.status === 404) {
throw new CurvegridResourceNotFoundError(
`Event query "${options.name}" not found`,
);
}
throw new CurvegridError(
`Failed to count event query records: ${error.message}`,
);
}
}