Ho trascorso l'ultima settimana cercando di capire come funzionino realmente i domini .night. Non leggendo una scheda tecnica, ma costruendo qualcosa che interagisca direttamente con la blockchain. Il risultato è un piccolo visualizzatore di profili. Digiti un nome come tomin.night e lui risolve il profilo direttamente dalla blockchain. Nessuna API del registrar. Nessun muro di autenticazione. Solo uno smart contract e un po' di JavaScript.
Quello che segue è come funziona, cosa ho imparato e le due trappole specifiche che mi hanno fatto perdere un intero pomeriggio.
Perché i nomi on-chain sono importanti
Su Midnight, i domini .night sono gestiti da Midnames. Invece di interrogare il server centrale di un'azienda, leggi direttamente da uno smart contract che risiede sulla chain. Il registro stesso detiene il dominio, il proprietario e qualsiasi campo del profilo che il proprietario abbia allegato. Poiché quei dati sono on-chain, l'identità è portabile. Non la stai affittando da una piattaforma che può cambiare i termini o interrompere il servizio. Se controlli le chiavi, controlli il nome.
Questo cambiamento è importante anche per gli sviluppatori. Quando costruisci qualcosa basandoti su un sistema DNS tradizionale, devi gestire limiti di frequenza (rate limits), chiavi API e promesse di uptime. Qui, lo stato del contratto è la fonte di verità. La tua applicazione lo legge nello stesso modo in cui la legge qualsiasi altra applicazione. Non esiste un livello API privilegiato.
Il codice è quasi fin troppo semplice
L'@midnames/sdk si occupa del lavoro pesante. Risolvere un dominio in un indirizzo e in un profilo richiede esattamente due righe:
const provider = createDefaultProvider({ networkId: "mainnet" });
const result = await resolveDomain(provider, "tomin.night");
Tutto qui. Il provider punta alla rete e il resolver comunica con il contratto. L'SDK restituisce un oggetto risultato che include un flag di successo. Se il dominio non esiste, non hai bisogno di livelli di gestione degli errori o blocchi try-catch per i fallimenti RPC. L'SDK ti comunica in modo pulito che non c'è nulla. Questo rende la creazione di interfacce utente sorprendentemente piacevole. Puoi creare un ramo basato sul flag di successo e mostrare uno stato di "non trovato" senza dover indovinare se il fallimento sia dovuto a un nome mancante o a un nodo non raggiungibile.
Cosa ricevi in risposta
Quando la ricerca ha successo, il payload contiene due elementi importanti.
Target è l'indirizzo del wallet a cui punta il dominio. Questa è la funzionalità principale. Trasforma un lungo indirizzo esadecimale in qualcosa che un essere umano può leggere, digitare e ricordare.
Fields contiene i dettagli del profilo. Qualunque cosa il proprietario abbia allegato al dominio — link social, avatar, record testuali — risiede all'interno di questa struttura. Questi campi non sono memorizzati nel cluster MongoDB di qualche azienda. Sono campi nello stato del contratto, il che significa che qualsiasi app che sappia come leggere il registro può renderizzare lo stesso profilo. Non è necessaria alcuna sincronizzazione del database.
Due trappole che mi hanno rallentato
Non tutto il processo di sviluppo è stato questione di due righe e un flag di successo. Ho incontrato due ostacoli specifici che vale la pena esporre per evitare che si ripetano.
Disallineamento della rete
L'SDK supporta sia l'ambiente mainnet che quello preprod. Ho passato un bel po' di tempo a fare il debugging di un dominio che "non esisteva". Il nome era corretto. Il codice sembrava giusto. Il provider era attivo. Il problema era che il mio script stava interrogando la preprod mentre il dominio stesso era registrato sulla mainnet. L'errore sembrava indicare un dominio mancante, ma in realtà era un contesto di rete mancante.
Se stai risolvendo un nome e ricevi un errore, controlla le impostazioni del provider prima di fare qualsiasi altra attività di debugging. Assicurati che il tuo networkId corrisponda alla rete in cui il dominio è stato effettivamente coniato. Questo è il tipo di errore che sembra ovvio a posteriori, ma è davvero difficile da individuare quando si è convinti che il problema sia la logica del contratto.
Problemi di serializzazione
I dati che tornano dall'SDK non sono JavaScript standard. Contengono valori BigInt e oggetti Map. Se provi a passarli direttamente in JSON.stringify per inviarli a un browser, l'operazione genererà un errore o perderà silenziosamente dei dati. BigInt non ha una rappresentazione JSON nativa e Map non si serializza come i normali oggetti.
Ho finito per scrivere un serializzatore personalizzato. Questo esamina l'oggetto risultato, converte i valori BigInt in stringhe e trasforma le istanze Map in oggetti regolari prima che la risposta lasci il server. Se stai costruendo un'API che serve dati di Midnight a un frontend, pianifica questo passaggio fin dall'inizio. Non dare per scontato che l'output dell'SDK sia immediatamente pronto per il frontend solo perché è JavaScript.
L'architettura
Ho mantenuto lo stack volutamente semplice. Il backend è un server Node che esegue Express. Importa @midnames/sdk, esegue la logica di risoluzione, gestisce le complessità della serializzazione e serve JSON pulito. Il frontend è semplice HTML e vanilla JavaScript. Nessun passaggio di build. Nessun framework. Nessun wallet adapter.
Ho scelto di eseguire l'SDK sul backend piuttosto che nel browser per alcune ragioni pratiche. Mantiene qualsiasi configurazione del provider fuori dal client, mi permette di avere un unico punto in cui sistemare il caos della serializzazione e significa che il frontend deve solo recuperare i dati e renderizzarli.
Ecco la parte che mi ha sorpreso di più: la risoluzione di un nome è un'operazione di lettura pubblica. Non serve una connessione al wallet. Non serve una firma. Non è necessario che l'utente effettui l'accesso con nulla. Se il dominio esiste, lo stato del contratto è visibile a chiunque lo richieda. Questa è una differenza significativa rispetto al tipico flusso web3, in cui ogni interazione inizia con "connetti il wallet". Leggere l'identità su Midnight è permissionless nello stesso modo in cui leggere un sito web pubblico è permissionless.
La vera lezione appresa
Costruire questo viewer mi ha ricordato che la parte più difficile dello sviluppo blockchain raramente è la blockchain stessa. Midnight ha già risolto il problema difficile: permettere alle persone di possedere il proprio nome e il proprio profilo senza un database centrale. La parte difficile, dal punto di vista di uno sviluppatore, è stata ricordare a quale rete mi stessi collegando e scrivere una funzione helper per pulire i tipi di dati.
Il protocollo ti offre un'identità portabile. Il tuo compito come sviluppatore è semplicemente leggerla correttamente e non intralciare l'utente. Mantieni l'architettura semplice, separa la logica rivolta alla chain dalla UI e tratta le letture pubbliche per quello che sono: normali query al database che, per caso, risiedono su un registro distribuito.
Se vuoi vedere il codice o provarlo tu stesso, il codice sorgente completo è disponibile su https://github.com/tomiin/midnames-profile-viewer.
