zonder
Version:
Ergonomic multi-chain indexing framework with dual runtime support for Ponder and Envio.
53 lines (52 loc) • 2.14 kB
JavaScript
import { safeWriteFileSync } from '../utils/safeWrite.js';
import { solidityTypeToGraphQLType } from './solidityTypeToGraphQLType.js';
/**
* Generates a GraphQL schema from Zonder configuration
*/
export function generateGraphQLSchema(config) {
let schema = '# This file is auto-generated by zonder. Do not edit manually.\n';
// Process each contract
Object.entries(config.contracts || {}).forEach(([contractName, abi]) => {
const events = abi.filter((item) => item.type === 'event');
events.forEach((event) => {
const typeName = `${contractName}_${event.name}`;
// Generate indexes
const indexes = [`@index(fields: ["chainId", "timestamp"])`];
// Add indexes for address fields
if (event.inputs && event.inputs.length > 0) {
event.inputs.forEach((input) => {
if (input.type === 'address') {
const fieldName = `evt_${input.name || 'param'}`;
indexes.push(`@index(fields: ["chainId", "${fieldName}"])`);
}
});
}
schema += `type ${typeName}\n ${indexes.join('\n ')} {\n`;
schema += ` id: ID!
chainId: Int!
txHash: String!
blockNumber: BigInt!
timestamp: BigInt!
logIndex: Int!
logAddress: String!\n`;
// Add event-specific fields
if (event.inputs && event.inputs.length > 0) {
schema += '\n';
event.inputs.forEach((input) => {
const fieldName = `evt_${input.name || 'param'}`;
const graphqlType = solidityTypeToGraphQLType(input.type);
schema += ` ${fieldName}: ${graphqlType}!\n`;
});
}
schema += '}\n\n';
});
});
return schema.trim() + '\n';
}
/**
* Generates and writes GraphQL schema to file
*/
export function generateAndWriteGraphQLSchema(config, overwrite = false) {
const schemaContent = generateGraphQLSchema(config);
safeWriteFileSync('schema.graphql', schemaContent, { overwrite });
}