Documentación

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

JavaScript
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ónTipoDescripción
networkstringRed que se consulta. Debe tener un subgraph desplegado.
apiKeystringAPI key de The Graph (se usa en el header Authorization).
subgraphUrlstringReemplaza 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:

JavaScript
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

JavaScript
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

JavaScript
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

JavaScript
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

JavaScript
const myOrgs = await query.getWatchers({
  owner: '0xYourWalletAddress',
});

Historial de propiedad como registro de auditoría

JavaScript
const history = await query.getWatcherOwnershipHistory('1');

for (const transfer of history) {
  console.log(transfer.previousOwner, '→', transfer.newOwner, 'at block', transfer.blockNumber);
}

Proyectos

Listar proyectos

JavaScript
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

JavaScript
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
}
Nota

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

JavaScript
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

JavaScript
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

JavaScript
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:

JavaScript
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

JavaScript
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

JavaScript
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:

JavaScript
// 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;
}