TextDAO Subgraph Coding Standards
This document outlines the coding standards and best practices for developing the TextDAO subgraph. Adhering to these standards ensures consistency, maintainability, and efficiency in our subgraph development process.
General Guidelines
- Use AssemblyScript for all subgraph development. Be mindful of its differences from TypeScript.
- Follow the AssemblyScript style guide for general coding practices.
- Use meaningful and descriptive names for variables, functions, and entities.
- Keep functions small and focused on a single responsibility.
- Comment your code, especially for complex logic or non-obvious implementations.
Schema Definition
- Use PascalCase for entity names (e.g.,
Proposal,Vote). - Use camelCase for field names (e.g.,
createdAt,approvedHeaderId). - Always specify the type for each field.
- Use
@entitydecorator for all entities. - Use
@derivedFromfor reverse lookups to avoid redundant data storage.
Example:
type Proposal @entity {
id: ID!
createdAt: BigInt!
votes: [Vote!]! @derivedFrom(field: "proposal")
}
Handler Functions
- Use descriptive names for handler functions that indicate the event being handled.
- Handle potential null values and use appropriate type checks.
- Use constants for fixed values like status enums.
- Implement error handling and logging for unexpected scenarios.
Example:
export function handleProposalCreated(event: ProposalCreatedEvent): void {
let proposal = new Proposal(event.params.proposalId.toString());
proposal.createdAt = event.block.timestamp;
proposal.proposer = event.params.proposer;
proposal.save();
log.info("Proposal created with ID: {}", [event.params.proposalId.toString()]);
}
Entity Management
- Always check if an entity exists before trying to load it.
- Use the
load()method to retrieve existing entities. - Initialize all required fields when creating new entities.
- Call
save()after modifying an entity.
Example:
const proposal = Proposal.load(proposalId);
if (proposal == null) {
proposal = new Proposal(proposalId);
proposal.createdAt = event.block.timestamp;
// Initialize other fields...
}
// Update fields...
proposal.save();
Type Safety
- Use strict null checks in AssemblyScript configuration.
- Explicitly handle null cases when loading entities.
- Use type assertions judiciously and only when necessary.
Performance Considerations
- Minimize the number of entity loads and saves in handler functions.
- Use derived fields instead of storing redundant data.
- Be cautious with loops and complex computations in handler functions.
Testing
- Write unit tests for all handler functions.
- Write integration tests for all scenario.
- Use the mock event function to test event handling.
- Test edge cases and potential error scenarios.
For more details on testing, refer to the Test Strategy document.
Documentation
- Use JSDoc comments for functions and complex logic.
- Keep the
README.mdfile up-to-date with setup and development instructions. - Document any assumptions or important decisions in code comments.
Example:
/**
* Handles the ProposalCreated event.
* @param event The ProposalCreated event emitted by the contract
*/
export function handleProposalCreated(event: ProposalCreatedEvent): void {
// Implementation...
}
Version Control
- Use descriptive commit messages that explain the purpose of the changes.
- Keep commits focused and atomic.
- Use feature branches for new developments and bug fixes.
Continuous Integration
- Ensure all tests pass before merging changes.
- Use the Graph CLI for local development and testing.
- Implement automatic deployment to a test subgraph for pull requests.
By following these coding standards, we ensure that our subgraph codebase remains clean, efficient, and maintainable. Always review and update these standards as our development practices evolve.