Consultar datos de energía
Todos los datos de EnergyAS son públicos y cualquiera puede consultarlos: sin controles de acceso ni registro previo. Esta guía cubre las tres formas de consultar datos, de la más simple a la de más bajo nivel.
| Enfoque | Ideal para |
|---|---|
| SDK (EnergyQuery) | Aplicaciones y scripts: métodos tipados, sin necesidad de GraphQL |
| Subgraph (GraphQL) | Consultas personalizadas, dashboards, analítica |
| Llamadas directas al contrato | Integraciones on-chain, auditoría de valores específicos |
Usar el SDK
La clase EnergyQuery del SDK es la forma más sencilla de obtener datos. Se encarga de la autenticación, la construcción de las solicitudes y el procesamiento de las respuestas. Consulta la Referencia del SDK completa para ver la configuración y todos los métodos disponibles.
import { EnergyQuery } from 'energy-attestation-sdk';
const query = new EnergyQuery({
network: 'polygon',
apiKey: 'YOUR_THEGRAPH_API_KEY',
});Consultas comunes
// Global protocol stats
const protocol = await query.getProtocol();
console.log(`${protocol.totalProjects} projects, ${protocol.totalGeneratedWh} Wh generated`);
// List organizations sorted by generation
const orgs = await query.getWatchers({
orderBy: 'totalGeneratedWh',
orderDirection: 'desc',
first: 10,
});
// Get an organization with all its projects
const org = await query.getWatcher('1');
console.log(org.projects);
// Get energy records for a project (most recent first)
const records = await query.getAttestations({
projectId: '5',
replaced: false,
orderBy: 'fromTimestamp',
orderDirection: 'desc',
});
// Daily snapshots for a chart
const snapshots = await query.getDailySnapshots({
projectId: '5',
dateFrom: '2025-01-01',
dateTo: '2025-01-31',
});Para la referencia completa de métodos, con filtros, paginación y todos los tipos de retorno, consulta Referencia del SDK: consulta de datos.
Usar el subgraph directamente
Si necesitas consultas GraphQL personalizadas más allá de lo que expone el SDK, puedes consultar el subgraph directamente. El subgraph indexa todos los eventos de EnergyRegistry en una API GraphQL consultable.
Endpoint
const SUBGRAPH_URL = 'https://gateway.thegraph.com/api/subgraphs/id/<SUBGRAPH_ID>';
async function querySubgraph(query, variables = {}) {
const response = await fetch(SUBGRAPH_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_API_KEY',
},
body: JSON.stringify({ query, variables }),
});
const { data } = await response.json();
return data;
}IDs del subgraph por red:
| Red | ID del subgraph |
|---|---|
| Polygon Amoy (testnet) | 33b8nJcqxLyH96eSyyHC9vsdvHifUXejLzMEtqLeySBC |
| Polygon | D8AgWoxUr3aDgWQCEy2hVeU8hnsrs5N3vmPSeGMphgEi |
| Celo | 9BM6kQzg7jtcbnphW7UXCGMmvJ2QtDkxnU8fqDYinUx1 |
Entidades indexadas
| Entidad | Formato del ID | Descripción |
|---|---|---|
| Protocol | "protocol" | Singleton con contadores globales |
| Resolver | dirección del resolver | Estado de autorización de los contratos resolver |
| EnergyType | uint8 como string (p. ej. "1") | Tipos de fuente de energía con el total generado |
| Watcher | watcherId como string (p. ej. "1") | Organizaciones de monitoreo |
| WatcherOwnershipTransfer | txHash-logIndex | Pista de auditoría inmutable de los cambios de propiedad |
| Project | projectId como string (p. ej. "1") | Sitios de energía individuales |
| EnergyAttestation | uid de EAS (hex bytes32) | Registros individuales con el arreglo de lecturas |
| ProjectAttester | projectId-address | Entradas de la lista blanca de emisores por proyecto |
| WatcherAttester | watcherId-address | Entradas de la lista blanca de emisores a nivel de organización |
| DailyEnergySnapshot | projectId-YYYY-MM-DD | Agregados diarios por proyecto para gráficos |
Consultas de ejemplo
Estadísticas del protocolo
{
protocol(id: "protocol") {
totalAttestations
totalGeneratedWh
totalConsumedWh
totalWatchers
totalProjects
}
}Listar organizaciones
{
watchers(
first: 10
orderBy: totalGeneratedWh
orderDirection: desc
) {
id
name
owner
totalGeneratedWh
totalConsumedWh
projectCount
}
}Detalle de una organización con sus proyectos
{
watcher(id: "1") {
id
name
owner
totalGeneratedWh
projects {
id
name
energyType { id name }
totalGeneratedWh
attestationCount
}
watcherAttesters {
attester
active
}
}
}Registros de un proyecto (solo los no reemplazados)
{
energyAttestations(
first: 50
orderBy: fromTimestamp
orderDirection: desc
where: { project: "1", replaced: false }
) {
id
energyWh
readings
fromTimestamp
toTimestamp
attester
metadataURI
txHash
}
}Cadena de reemplazos: seguir las correcciones
Cuando se corrige un registro, el original se marca como replaced: true y apunta a la nueva versión:
{
energyAttestation(id: "0xoriginaluid...") {
id
replaced
replacedBy {
id
energyWh
readings
}
}
}Snapshots diarios de energía (serie temporal)
{
dailyEnergySnapshots(
first: 30
orderBy: timestamp
orderDirection: desc
where: { project: "1" }
) {
date
generatedWh
consumedWh
attestationCount
}
}Distribución de energía por tipo
{
energyTypes(
orderBy: totalGeneratedWh
orderDirection: desc
where: { registered: true }
) {
id
name
totalGeneratedWh
}
}Paginación
# Page 1
{ watchers(first: 10, skip: 0) { id name } }
# Page 2
{ watchers(first: 10, skip: 10) { id name } }The Graph limita first a 1000. Usa skip para recorrer conjuntos de resultados más grandes.
Consejos
- Los IDs de las entidades son strings. Consulta
watcher(id: "1"), nowatcher(id: 1). - El tipo de energía es una relación. Consulta
energyType { id name }, no es un valor escalar. - Los consumidores tienen
energyTypeennull. Filtra los generadores conwhere: { energyType_not: null }. - Los timestamps son strings BigInt. The Graph ordena correctamente cuando los ordenas como strings.
- Usa
replaced: falsepara excluir los registros corregidos y mostrar solo la versión vigente.
Llamadas directas al contrato
Para integraciones on-chain o cuando necesitas leer valores directamente del contrato, puedes llamar a las funciones de EnergyRegistry mediante ethers, viem o cualquier librería web3.
const watcher = await registry.getWatcher(watcherId);
console.log(watcher.name, watcher.owner);
const projects = await registry.getWatcherProjects(watcherId);Totales de energía
const generated = await registry.getTotalGeneratedEnergy(projectId);
const consumed = await registry.getTotalConsumedEnergy(projectId);
console.log(`Generated: ${generated} Wh, Consumed: ${consumed} Wh`);
// Watcher-level totals
const totalGen = await registry.getTotalGeneratedEnergyByWatcher(watcherId);
const totalCon = await registry.getTotalConsumedEnergyByWatcher(watcherId);Verificar si un periodo ya fue atestado
import { ZeroHash } from 'ethers';
const uid = await registry.getAttestedPeriodUID(projectId, fromTimestamp, toTimestamp);
const isAttested = uid !== ZeroHash;Seguir la cadena de reemplazos
// Get the timestamp after the last attested period
const lastTs = await registry.getProjectLastTimestamp(projectId);
// Walk the replacement chain for an attestation
let currentUid = originalUid;
let replacementUid = await registry.getReplacementUID(currentUid);
while (replacementUid !== ZeroHash) {
currentUid = replacementUid;
replacementUid = await registry.getReplacementUID(currentUid);
}
// currentUid is now the latest version of the recordVerificar la autorización de un emisor
const isAuthorized =
await registry.isProjectAttester(projectId, wallet) ||
await registry.isWatcherAttester(watcherId, wallet);Indexación de eventos
Si construyes tu propio indexador en lugar de usar el subgraph, los eventos clave son:
EnergyAttested: cada nuevo registro, con el arreglo completo de lecturasEnergyReplaced: cada corrección, con los valores de energía anterior y nuevoProjectRegistered/ProjectDeregistered: ciclo de vida del proyectoWatcherRegistered: incorporación de una nueva organizaciónWatcherAttesterAdded/WatcherAttesterRemoved: cambios de autorización
Consulta la Referencia de eventos para ver las firmas completas de los parámetros.