zama-subgraph
Best practices for building app-facing subgraphs and GraphQL integrations in this monorepo. Use when: (1) Setting up a new subgraph package, (2) Designing `schema.graphql` entities and relationships, (3) Choosing manifest strategy (`subgraph.yaml`, `networks.json`, or templating), (4) Writing AssemblyScript mappings and entity ID helpers, (5) Deciding when to use snapshots, immutable entities, templates, or helper entities, (6) Wiring app-side GraphQL queries against the subgraph, (7) Reviewing subgraph performance, maintainability, or testing strategy. Derived from studying production DeFi subgraphs and aligned to Zama's local stack.
What this skill does
# Subgraph Best Practices
## Core Model
### A Subgraph Has Two Jobs
1. Maintain a small set of **current-state entities** that the app can query cheaply.
2. Record **event/history entities** only when the product needs auditability, timelines, or
activity feeds.
That framing should drive almost every design choice.
If a field is needed to render the current app state, keep it on a mutable entity. If a record
exists only because an event happened, make it an immutable event entity.
### Optimize For Query Shape, Not Indexing Cleverness
The best subgraph is not the one with the fanciest mapping layer. It is the one whose schema matches
the actual product queries.
Keep a current-state `Batch`, `Position`, `Vault`, `Market`, or equivalent entity. Add event/history
entities only where the UI or operators need them.
## Configuration Strategy
### Default: Static `subgraph.yaml` + `networks.json`
This should be the default for app-facing subgraphs.
Use it when:
- the same data sources exist on every network
- only addresses and start blocks vary
- you want simple builds like `graph build --network sepolia`
This is the right choice for a fixed-contract subgraph.
### Use Manifest Templating Only When Topology Changes
Use Mustache or similar templating when:
- some data sources only exist on some networks
- the manifest shape changes per deployment
- you need conditional handlers, grafting, or chain-specific manifest blocks
Do not introduce templating just because multiple networks exist. If `networks.json` is enough, use
it.
### Use Runtime Templates For Factory-Created Contracts
If contracts are created after indexing starts, use Graph templates.
```yaml
templates:
- kind: ethereum/contract
name: Vault
network: mainnet
source:
abi: Vault
mapping:
kind: ethereum/events
apiVersion: 0.0.7
language: wasm/assemblyscript
file: ./src/mappings.ts
entities:
- Vault
abis:
- name: Vault
file: ./abis/Vault.json
eventHandlers:
- event: Deposit(indexed address,uint256)
handler: handleDeposit
```
```typescript
import { Vault as VaultTemplate } from "../generated/templates";
export function handleVaultCreated(event: VaultCreated): void {
VaultTemplate.create(event.params.vault);
}
```
## Schema Design
### Current-State Entities vs Event Entities
Use **mutable entities** for current state:
```graphql
type Batch @entity {
id: ID!
state: BatchState!
exchangeRate: BigInt
finalizedAtBlock: BigInt
memberships: [PositionMembership!]! @derivedFrom(field: "batch")
}
```
Use **immutable entities** for event records:
```graphql
type BatchFinalizedEvent @entity(immutable: true) {
id: Bytes!
batch: Batch!
exchangeRate: BigInt!
blockNumber: BigInt!
txHash: Bytes!
}
```
Rule:
- if the entity should change over time, it is mutable
- if the entity is a record of one event occurrence, it should usually be immutable
### `@derivedFrom` Is The Default For Reverse Relations
Do not store arrays of related entities directly when the relation can be expressed from the child
side.
```graphql
type Batch @entity {
id: ID!
memberships: [PositionMembership!]! @derivedFrom(field: "batch")
}
type PositionMembership @entity {
id: ID!
batch: Batch!
account: Bytes!
}
```
Why:
- cleaner writes
- smaller mutable state surface
- better alignment with how Graph relationships are meant to be modeled
Important nuance:
- this applies to **entity relationship arrays**
- it does not mean "never use arrays anywhere"
Small scalar arrays can be fine. Relationship arrays should almost always be `@derivedFrom`.
### Snapshots Are A Product Feature
Add snapshots only when the app or analytics layer needs:
- time-series charts
- daily or hourly rollups
- point-in-time financial metrics
- unique-user or usage metrics by interval
Do not add snapshots just because other subgraphs have them.
For a simple app-facing state machine, snapshots are often unnecessary complexity.
If you need snapshots, make them deterministic:
```typescript
import { Bytes } from "@graphprotocol/graph-ts";
export function makeDailySnapshotId(entityId: Bytes, timestamp: i32): Bytes {
return entityId.concat(Bytes.fromI32(timestamp / 86400));
}
```
## ID Strategy
### Use `Bytes!` When The Identity Is Naturally Binary
Use `Bytes!` for:
- addresses
- tx-hash + log-index event IDs
- binary composite IDs built from addresses and fixed-width values
```typescript
import { Bytes, ethereum } from "@graphprotocol/graph-ts";
export function makeEventId(event: ethereum.Event): Bytes {
return event.transaction.hash.concatI32(event.logIndex.toI32());
}
```
This should be the default for event IDs.
### Use `ID!`/string When The Identity Is Semantic
Use string IDs when:
- the entity key is semantic rather than binary
- you need readable or versioned composites
- the identifier contains mixed domains like chain ID + address + protocol-side counter
```typescript
import { Address, BigInt } from "@graphprotocol/graph-ts";
export function makeBatchEntityId(chainId: i32, batcher: Address, batchId: BigInt): string {
return `${chainId.toString()}-${batcher.toHexString()}-${batchId.toString()}`;
}
```
Do not force `Bytes!` everywhere. Use the ID shape that makes collisions impossible and the model
maintainable.
## Mapping Structure
### Default To Flat Helpers
For most app-facing subgraphs, flat helpers are the right starting point.
Typical layout:
```text
src/
├── mappings.ts
├── entity-ids.ts
└── helpers.ts
```
Use flat helpers when:
- handlers touch only a few entities
- the state machine is small
- there is little reuse across handlers
### Introduce Managers Only When The Domain Demands It
Manager classes are justified when handlers repeatedly update many entities with tightly coupled
logic.
The trigger is a single handler that updates current state, counters, snapshots, event entities, and
lifecycle/versioning helpers all at once. For a simple subgraph, managers are usually
over-architecture.
### Keep Handlers Thin
Handlers should do four things:
1. Decode event intent.
2. Load or create the required entities.
3. Update current state and write event entities.
4. Delegate repeated logic to helpers.
```typescript
export function handleJoined(event: Joined): void {
const batch = getOrCreateBatch(event);
const membership = getOrCreateMembership(event, batch);
membership.status = "active";
membership.joinedAtBlock = event.block.number;
membership.save();
batch.state = "pending";
batch.save();
}
```
### Helper Entities Are Fine When They Buy Determinism
Use helper entities for things like:
- unique-account counting by interval
- lifecycle counters
- versioned position reopening
Do not add helper entities unless they remove ambiguity from the model.
## Performance And Manifest Knobs
### Pruning Is A Workload Decision
Use:
```yaml
indexerHints:
prune: auto
```
when the subgraph is primarily app-facing and you care about current-state reads more than
historical entity versions.
Use:
```yaml
indexerHints:
prune: never
```
when historical state retention matters.
Do not treat `prune: auto` as a universal best practice. It is a default for app-facing products,
not for every subgraph.
### Enable Receipts Only When Needed
```yaml
eventHandlers:
- event: LiquidationCall(...)
handler: handleLiquidationCall
receipt: true
```
Do not enable `receipt: true` globally. It is a targeted feature.
### Prefer Event-Complete Contracts
The cleanest subgraph is one whose contracts emit the data the mappings need.
Contracts should emit enough data for the mapping to update state directly. Selective `eth_call` for
metadata or unavoidable derived state is acceptable.
## Testing
### Matchstick Is Required Here
The external repos are inconsistent. We should not copy that.
For this repo, Matchstick tests are part of the standard.
TestRelated in Backend & APIs
jfrog
IncludedInteract with the JFrog Platform via the JFrog CLI and REST/GraphQL APIs. Use this skill when the user wants to manage Artifactory repositories, upload or download artifacts, manage builds, configure permissions, manage users and groups, work with access tokens, configure JFrog CLI servers, search artifacts, manage properties, set up replication, manage JFrog Projects, run security audits or scans, look up CVE details, query exposures scan results from JFrog Advanced Security, manage release bundles and lifecycle operations, aggregate or export platform data, or perform any JFrog Platform administration task. Also use when the user mentions jf, jfrog, artifactory, xray, distribution, evidence, apptrust, onemodel, graphql, workers, mission control, curation, advanced security, exposures, or any JFrog product name.
cupynumeric-migration-readiness
IncludedPre-migration readiness assessor for porting NumPy to cuPyNumeric. Use BEFORE substantial porting work begins when the user asks whether code will scale on GPU, whether they should migrate to cuPyNumeric, which NumPy patterns transfer cleanly, what must be refactored before porting, or mentions pre-port assessment, scaling analysis, or refactor planning. Inspect the user's source code, look up NumPy usage, cross-reference the cuPyNumeric API support manifest, and distinguish distributed-scaling-friendly patterns from blockers such as unsupported APIs, scalar synchronization, host round-trips, Python/object-heavy control flow, shape/data-dependent branching, and in-place mutation hazards. Produce a verdict of READY, LIGHT REFACTOR, SIGNIFICANT REFACTOR, or NOT RECOMMENDED, with concrete refactor pointers.
alibabacloud-data-agent-skill
IncludedInvoke Alibaba Cloud Apsara Data Agent for Analytics via CLI to perform natural language-driven data analysis on enterprise databases. Data Agent for Analytics is an intelligent data analysis agent developed by Alibaba Cloud Database team for enterprise users. It automatically completes requirement analysis, data understanding, analysis insights, and report generation based on natural language descriptions. This tool supports: discovering data resources (instances/databases/tables) managed in DMS, initiating query or deep analysis sessions, real-time progress tracking, and retrieving analysis conclusions and generated reports. Use this Skill when users need to query databases, analyze data trends, generate data reports, ask questions in natural language, or mention "Data Agent", "data analysis", "database query", "SQL analysis", "data insights".
token-optimizer
IncludedReduce OpenClaw token usage and API costs through smart model routing, heartbeat optimization, budget tracking, and native 2026.2.15 features (session pruning, bootstrap size limits, cache TTL alignment). Use when token costs are high, API rate limits are being hit, or hosting multiple agents at scale. The 4 executable scripts (context_optimizer, model_router, heartbeat_optimizer, token_tracker) are local-only — no network requests, no subprocess calls, no system modifications. Reference files (PROVIDERS.md, config-patches.json) document optional multi-provider strategies that require external API keys and network access if you choose to use them. See SECURITY.md for full breakdown.
resend-cli
IncludedUse this skill when the task is specifically about operating Resend from an AI agent, terminal session, or CI job via the official resend CLI: installing/authenticating the CLI, sending/listing/updating/cancelling emails, batch sends, domains and DNS, webhooks and local listeners, inbound receiving, contacts, topics, segments, broadcasts, templates, API keys, profiles, or debugging Resend CLI/API failures. Trigger on mentions of Resend CLI, `resend`, `resend doctor`, `resend emails send`, `resend domains`, `resend webhooks listen`, `resend emails receiving`, or agent-friendly terminal automation.
alibabacloud-odps-maxframe-coding
IncludedUse this skill for MaxFrame SDK development and documentation navigation on Alibaba Cloud MaxCompute (ODPS). Helps answer MaxFrame API, concept, official example, and supported pandas API questions; create data processing programs; read/write MaxCompute tables; debug jobs (remote or local); and build custom DPE runtime images. Trigger when users mention MaxFrame, MaxCompute with MaxFrame, ODPS table processing, DPE runtime, MaxFrame docs/examples, DataFrame/Tensor operations, or GPU runtime setup. Works for both English and Chinese queries about Alibaba Cloud data processing with MaxFrame.