EnergyQuery: lectura de datos
EnergyQuery es un cliente tipado para el subgraph de EnergyAS. Se encarga de la autenticación, la construcción de las solicitudes GraphQL y el procesamiento de las respuestas. No requiere wallet ni clave privada.
Configuración
import { EnergyQuery } from 'energy-attestation-sdk';
const query = new EnergyQuery({
network: 'polygon', // 'amoy' | 'polygon' | 'celo'
apiKey: 'YOUR_API_KEY', // The Graph API key — get one at thegraph.com/studio
});Opciones de configuración:
| Opción | Tipo | Descripción |
|---|---|---|
network | string | Red que se consulta. Debe tener un subgraph desplegado. |
apiKey | string | API key de The Graph (se usa en el header Authorization). |
subgraphUrl | string | Reemplaza directamente la URL del subgraph. Úsala en desarrollo local o en despliegues personalizados en lugar de apiKey. |
Necesitas apiKey (para los endpoints estándar del subgraph) o subgraphUrl (para un endpoint personalizado o autoalojado). Si das ambos, se usa subgraphUrl y se ignora apiKey.
Estadísticas del protocolo
Obtén los totales globales de todas las redes:
const protocol = await query.getProtocol();
console.log(protocol.totalWatchers); // number of registered organizations
console.log(protocol.totalProjects); // number of energy sites
console.log(protocol.totalAttestations); // total records submitted
console.log(protocol.totalGeneratedWh); // cumulative generated energy (Wh)
console.log(protocol.totalConsumedWh); // cumulative consumed energy (Wh)Tipos de energía
const types = await query.getEnergyTypes();
for (const t of types) {
console.log(t.id, t.name, t.totalGeneratedWh);
}
// e.g. "1" "Solar PV" "42000000"Organizaciones (watchers)
Listar todas las organizaciones
const watchers = await query.getWatchers({
first: 20,
skip: 0,
orderBy: 'totalGeneratedWh',
orderDirection: 'desc',
registered: true, // optional: filter active orgs only
});
for (const w of watchers) {
console.log(w.id, w.name, w.owner, w.projectCount);
}Obtener una organización con todo su detalle
const watcher = await query.getWatcher('1'); // pass watcherId as string
if (watcher) {
console.log(watcher.name);
console.log(watcher.projects); // list of projects
console.log(watcher.watcherAttesters); // authorized submitters
console.log(watcher.ownershipHistory); // ownership transfer log
}Filtrar por dirección del propietario
const myOrgs = await query.getWatchers({
owner: '0xYourWalletAddress',
});Historial de propiedad como registro de auditoría
const history = await query.getWatcherOwnershipHistory('1');
for (const transfer of history) {
console.log(transfer.previousOwner, '→', transfer.newOwner, 'at block', transfer.blockNumber);
}Proyectos
Listar proyectos
const projects = await query.getProjects({
first: 50,
orderBy: 'totalGeneratedWh',
orderDirection: 'desc',
watcherId: '1', // optional: filter by organization
energyTypeId: '1', // optional: '1' = Solar PV, '0' = Consumer, etc.
registered: true,
});Obtener un proyecto
const project = await query.getProject('5');
if (project) {
console.log(project.name);
console.log(project.energyType?.name); // null for consumers
console.log(project.totalGeneratedWh);
console.log(project.attestationCount);
console.log(project.metadataURI); // link to metadata (IPFS or HTTPS)
console.log(project.lastToTimestamp); // end of the last attested period
}Consumidores vs generadores: los proyectos consumidores tienen energyType: null. Para filtrar solo generadores, usa energyTypeId con un ID de tipo distinto de cero. Para obtener solo consumidores, omite energyTypeId y filtra del lado del cliente.
Registros de energía (atestaciones)
Listar los registros de un proyecto
const records = await query.getAttestations({
projectId: '5',
replaced: false, // exclude corrected records
orderBy: 'fromTimestamp',
orderDirection: 'desc',
first: 50,
});
for (const r of records) {
console.log(r.fromTimestamp, r.toTimestamp, r.energyWh);
console.log(r.readings); // array of per-interval Wh values (as strings)
console.log(r.attester); // address that submitted the record
console.log(r.txHash); // transaction hash
}Obtener un registro por UID
const record = await query.getAttestation('0xabcd...');
if (record) {
console.log(record.replaced); // true if this record was corrected
console.log(record.replacedBy?.id); // UID of the correction
console.log(record.replaces?.id); // UID of the original this corrected
}Filtrar por rango de fechas
const startOfMonth = Math.floor(new Date('2025-01-01').getTime() / 1000).toString();
const endOfMonth = Math.floor(new Date('2025-02-01').getTime() / 1000).toString();
const records = await query.getAttestations({
projectId: '5',
fromTimestamp_gte: startOfMonth,
fromTimestamp_lte: endOfMonth,
replaced: false,
});Snapshots diarios (series de tiempo)
El subgraph preagrega los datos de energía en intervalos diarios, la forma más rápida de construir gráficos:
const snapshots = await query.getDailySnapshots({
projectId: '5',
dateFrom: '2025-01-01', // YYYY-MM-DD (inclusive)
dateTo: '2025-01-31', // YYYY-MM-DD (inclusive)
orderDirection: 'asc',
first: 365,
});
for (const day of snapshots) {
console.log(day.date, day.generatedWh, day.consumedWh, day.attestationCount);
}Remitentes autorizados
Remitentes a nivel de proyecto
const submitters = await query.getProjectAttesters('5', { active: true });
for (const s of submitters) {
console.log(s.attester, s.active, s.addedAt);
}Remitentes a nivel de organización
const submitters = await query.getWatcherAttesters('1', { active: true });Paginación
Todos los métodos de listado aceptan first y skip. El subgraph limita first a 1000:
// Page through all projects
let skip = 0;
let all = [];
while (true) {
const page = await query.getProjects({ first: 1000, skip });
all = all.concat(page);
if (page.length < 1000) break;
skip += 1000;
}