Capitolo 7 di 9

Il programma che porta il prezzo ogni mattina

Obiettivo. Capire come un programma fuori dalla blockchain legge i prezzi e li scrive nell'oracolo ogni giorno.

Il contratto non si sveglia da solo: serve qualcuno che, ogni mattina, gli porti il numero. Quel qualcuno è un piccolo programma (il backend) che gira su un computer sempre acceso.

Analogia. È il fattorino del giornale: ogni mattina alle 8:30 ritira i prezzi dal Ministero, li controlla e li consegna al notaio (il contratto). Se non li ritira, il foglio sul tavolo resta quello di ieri.

Il programma fa cinque passi: 1) interroga il Ministero, 2) calcola la mediana, 3) legge il prezzo del POL, 4) salva tutto in un piccolo archivio locale, 5) chiama setPrices sul contratto firmando con la chiave dell'updater, l'unico indirizzo con il ruolo del capitolo 4. Ogni giorno è registrato una volta sola, quindi rilanciarlo non crea doppioni.

import { Contract, JsonRpcProvider, Wallet } from "ethers";

function median(values) {
  const s = [...values].sort((a, b) => a - b);
  const m = s.length >> 1;
  return s.length % 2 ? s[m] : (s[m - 1] + s[m]) / 2;
}

const abi = ["function setPrices(uint256 fuelEurPerLitre, uint256 polEur, uint64 sourceDate)"];
const provider = new JsonRpcProvider(process.env.RPC_URL);
const wallet = new Wallet(process.env.UPDATER_PRIVATE_KEY, provider);
const oracle = new Contract(process.env.ORACLE_ADDRESS, abi, wallet);

const fuelEur = median(pricesOfStations);   // e.g. 1.989
const polEur = 0.10;                        // from a price service
const scale = (x) => BigInt(Math.round(x * 1e6));
const today = Math.floor(Date.parse(new Date().toISOString().slice(0, 10)) / 1000);

const tx = await oracle.setPrices(scale(fuelEur), scale(polEur), today);
await tx.wait();

Nel progetto il programma parte da solo alle 8:30 (ora di Roma) con un timer. Se la richiesta fallisce, riprova tre volte a dieci minuti l'una dall'altra.

Se la fonte non risponde

Se il Ministero è irraggiungibile o cambia formato, il programma non scrive nulla. Sulla blockchain resta il prezzo di ieri, con la sua data. Dopo 3 giorni, isFresh (capitolo 4) risponde «no» e buy() e sell() si fermano con l'errore «prezzo vecchio». È una scelta voluta: meglio fermarsi che operare su un numero che non rappresenta più la realtà.

Prova tu

Esegui nel terminale con Node.js la sola funzione median su una lista a tua scelta di 6 numeri (numero pari) e verifica a mano che sia la media dei due centrali.

Cosa hai imparato