Documentación

EnergySDK: escritura de datos

EnergySDK se encarga de todas las operaciones de escritura on-chain: registrar organizaciones y proyectos, gestionar remitentes autorizados y enviar registros de energía. Requiere una wallet firmante y usa ethers v6 internamente.

Configuración

Hay dos formas de crear una instancia del SDK, según tu entorno.

Desde una clave privada (Node.js / IoT / backend)

JavaScript
import { EnergySDK } from 'energy-attestation-sdk';

const sdk = await EnergySDK.fromPrivateKey({
  network: 'polygon',
  privateKey: process.env.PRIVATE_KEY,
  // rpcUrl: 'https://...',  // optional — uses the network default if omitted
});

console.log('Signing as:', sdk.address);

Desde una wallet del navegador (MetaMask / WalletConnect)

JavaScript
import { BrowserProvider } from 'ethers';
import { EnergySDK } from 'energy-attestation-sdk';

const provider = new BrowserProvider(window.ethereum);
const signer = await provider.getSigner();

const sdk = await EnergySDK.fromSigner({
  network: 'polygon',
  signer,
});

Ambos métodos de fábrica validan el ID de cadena conectado contra la red especificada y lanzan un ConfigurationError si no coinciden.

Organizaciones (watchers)

Registrar una nueva organización

JavaScript
const { watcherId, txHash } = await sdk.watchers.createWatcher('Greenfield Energy');

console.log('Organization ID:', watcherId.toString());  // e.g. 7n
console.log('Transaction:', txHash);

La wallet que hace esta llamada se convierte en la propietaria de la organización. El propietario puede autorizar remitentes, crear proyectos y transferir la propiedad.

Transferir la propiedad de la organización

JavaScript
await sdk.watchers.transferWatcherOwnership(watcherId, '0xNewOwnerAddress');

Proyectos

Registrar un proyecto

JavaScript
import { EnergyType } from 'energy-attestation-sdk';

const { projectId, txHash } = await sdk.projects.createProject(
  watcherId,           // organization ID
  'Solar Farm Alpha',  // display name
  EnergyType.SOLAR_PV,  // energy type (or pass the numeric value directly)
);

console.log('Project ID:', projectId.toString());

Valores del enum EnergyType:

EnumValorDescripción
EnergyType.CONSUMER0Sitio consumidor (centro de datos, flota de vehículos eléctricos, etc.)
EnergyType.SOLAR_PV1Solar fotovoltaica
EnergyType.WIND_ONSHORE2Eólica terrestre
EnergyType.WIND_OFFSHORE3Eólica marina
EnergyType.HYDRO4Hidroeléctrica
EnergyType.BIOMASS5Biomasa
EnergyType.GEOTHERMAL6Geotérmica
EnergyType.OCEAN_TIDAL7Oceánica / mareomotriz
EnergyType.NUCLEAR8Nuclear
EnergyType.NATURAL_GAS9Gas natural
EnergyType.COAL10Carbón
EnergyType.OIL11Petróleo
EnergyType.STORAGE_DISCHARGE12Descarga de almacenamiento en baterías
EnergyType.HYDROGEN_FUEL_CELL13Celda de combustible de hidrógeno
Nota

El tipo de energía es permanente. No puedes cambiar el tipo de un proyecto después de registrarlo. Esto evita la clasificación errónea de datos de generación y consumo.

Adjuntar metadata a un proyecto

JavaScript
await sdk.projects.setProjectMetadataURI(
  projectId,
  'ipfs://QmYourMetadataCID',  // or any HTTPS URL
);

Consulta Metadata del proyecto para ver el formato JSON esperado.

Dar de baja un proyecto

Dar de baja un proyecto bloquea nuevos envíos, pero conserva de forma permanente todos los registros históricos:

JavaScript
await sdk.projects.deregisterProject(projectId);

Transferir un proyecto a otra organización

JavaScript
await sdk.projects.transferProject(projectId, targetWatcherId);

Remitentes autorizados (atestadores)

Debes autorizar al menos una wallet antes de poder enviar registros de energía para un proyecto.

Autorizar a un remitente para un proyecto específico

JavaScript
await sdk.attesters.addAttester(projectId, '0xDeviceWalletAddress');

Autorizar a varios remitentes a la vez

JavaScript
await sdk.attesters.addAttesters(projectId, [
  '0xDevice1Address',
  '0xDevice2Address',
]);

Autorizar a un remitente en todos los proyectos de una organización

Útil para operadores de respaldo o auditores manuales:

JavaScript
await sdk.attesters.addWatcherAttester(watcherId, '0xOperatorAddress');

Quitar la autorización

JavaScript
await sdk.attesters.removeAttester(projectId, '0xDeviceWalletAddress');
await sdk.attesters.removeWatcherAttester(watcherId, '0xOperatorAddress');

Envío de registros de energía

Los registros de energía (atestaciones) son la unidad de datos central de EnergyAS. Cada registro cubre un período de tiempo y contiene una lectura por intervalo.

Enviar un registro individual

JavaScript
const { uid, txHash } = await sdk.attestations.attest({
  projectId: 1,
  readings: [500_000n, 510_000n, 495_000n],  // Wh per interval, as BigInt
  readingIntervalMinutes: 60,                  // interval length in minutes
  fromTimestamp: 1735689600,                   // Unix timestamp (start of first interval)
  method: 'smart-meter-api',                   // collection method label
  metadataURI: 'ipfs://QmMetadataCID',         // optional — attach evidence
});

console.log('Record UID:', uid);
console.log('Transaction:', txHash);

La longitud del array readings y readingIntervalMinutes definen juntos el período cubierto. Tres lecturas de 60 minutos que empiezan en fromTimestamp cubren una ventana de 3 horas. El contrato impide enviar un período que se solape con cualquier registro existente del mismo proyecto.

Todos los campos:

CampoTipoObligatorioDescripción
projectIdnumber | bigintSíID del proyecto
readingsbigint[]SíWh por intervalo. Usa 0n para períodos sin generación
readingIntervalMinutesnumberSíMinutos por lectura (p. ej., 15, 30, 60)
fromTimestampnumberSíTimestamp Unix del inicio del primer intervalo
methodstringSíEtiqueta de texto libre para el método de recolección
metadataURIstringNoURI que apunta a documentación de respaldo

Enviar varios registros en una transacción

Los envíos por lotes consumen menos gas cuando tienes varios períodos que reportar:

JavaScript
const { uids, txHash } = await sdk.attestations.attestBatch([
  {
    projectId: 1,
    readings: [500_000n, 510_000n],
    readingIntervalMinutes: 60,
    fromTimestamp: 1735689600,
    method: 'smart-meter-api',
  },
  {
    projectId: 1,
    readings: [490_000n, 505_000n],
    readingIntervalMinutes: 60,
    fromTimestamp: 1735696800,
    method: 'smart-meter-api',
  },
]);

console.log('Submitted UIDs:', uids);

Corregir un registro existente

Si un registro contenía un error, envía un reemplazo que haga referencia al original mediante refUID. El original se marca como reemplazado y se excluye de los totales; en su lugar entra en vigor el nuevo registro:

JavaScript
const { uid } = await sdk.attestations.overwriteAttestation({
  refUID: '0xOriginalRecordUID',  // the record being corrected
  projectId: 1,
  readings: [512_000n, 508_000n, 499_000n],  // corrected values
  readingIntervalMinutes: 60,
  fromTimestamp: 1735689600,
  method: 'smart-meter-api-corrected',
  metadataURI: 'ipfs://QmCorrectionAuditReport',
});
Nota

Nota: el contrato bloquea la revocación directa. Las correcciones siempre deben hacerse mediante overwriteAttestation, que conserva un registro de auditoría completo.

Reportar un período sin generación

Si un sitio estuvo fuera de línea o no generó durante un período, usa attestZeroPeriod. Continúa automáticamente desde el último timestamp atestado:

JavaScript
const { uid } = await sdk.attestations.attestZeroPeriod({
  projectId: 1,
  interval: 60,          // Interval enum value or minutes
  method: 'manual-zero-report',
  metadataURI: 'ipfs://QmMaintenanceLog',  // optional
});

Esto equivale a llamar a attest con readings: [0n] a partir de getProjectLastTimestamp().

Estimación de gas

Cada método de escritura tiene un método estimate*Gas correspondiente para verificaciones previas:

JavaScript
const gas = await sdk.attestations.estimateAttestGas(params);
console.log('Estimated gas:', gas.toString());

const gas2 = await sdk.watchers.estimateCreateWatcherGas('My Org');
const gas3 = await sdk.projects.estimateCreateProjectGas(watcherId, 'Site A', EnergyType.SOLAR_PV);