గత వారం నేను .night డొమైన్‌లు నిజంగా ఎలా పనిచేస్తాయో అర్థం చేసుకోవడానికి ప్రయత్నించాను. ఏదో స్పెసిఫికేషన్ షీట్ చదివి కాదు, నేరుగా చైన్‌తో అనుసంధానించబడే ఒక ప్రాజెక్ట్‌ను నిర్మించడం ద్వారా తెలుసుకున్నాను. దాని ఫలితంగా ఒక చిన్న ప్రొఫైల్ వ్యూయర్ సిద్ధమైంది. మీరు tomin.night వంటి పేరును టైప్ చేస్తే, అది నేరుగా బ్లాక్‌చెయిన్ నుండి ప్రొఫైల్‌ను రిజాల్వ్ (resolve) చేస్తుంది. ఎటువంటి రిజిస్ట్రార్ API అవసరం లేదు. ఎటువంటి ఆథెంటికేషన్ (auth) అడ్డంకులు లేవు. కేవలం ఒక స్మార్ట్ కాంట్రాక్ట్ మరియు కొంత JavaScript మాత్రమే.

ఇది ఎలా పనిచేస్తుంది, నేను ఏమి నేర్చుకున్నాను మరియు నా సాయంత్రాన్ని వృథా చేసిన రెండు నిర్దిష్టమైన చిక్కుల (traps) గురించి ఇక్కడ ఉంది.

ఆన్-చైన్ పేర్లు ఎందుకు ముఖ్యమైనవి

Midnightలో, .night డొమైన్‌లను Midnames నిర్వహిస్తుంది. ఏదైనా కంపెనీ యొక్క సెంట్రల్ సర్వర్‌ను క్వెరీ (query) చేసే బదులు, మీరు నేరుగా చైన్‌పై ఉండే స్మార్ట్ కాంట్రాక్ట్ నుండి డేటాను చదువుతారు. రిజిస్ట్రీయే డొమైన్, యజమాని మరియు యజమాని జత చేసిన ప్రొఫైల్ ఫీల్డ్‌లను కలిగి ఉంటుంది. ఆ డేటా ఆన్-చైన్‌లో ఉండటం వల్ల, మీ గుర్తింపు (identity) పోర్టబుల్‌గా ఉంటుంది. నిబంధనలను మార్చగల లేదా సేవలను నిలిపివేయగల ప్లాట్‌ఫారమ్ నుండి మీరు దీనిని అద్దెకు తీసుకోవడం లేదు. మీ దగ్గర కీలు (keys) ఉంటే, ఆ పేరుపై మీకు నియంత్రణ ఉంటుంది.

ఈ మార్పు డెవలపర్లకు కూడా చాలా ముఖ్యం. మీరు సాంప్రదాయ DNS సిస్టమ్‌పై పని చేస్తున్నప్పుడు, రేట్ లిమిట్స్ (rate limits), API కీలు మరియు అప్‌టైమ్ (uptime) వాగ్దానాలతో డీల్ చేయాల్సి ఉంటుంది. ఇక్కడ, కాంట్రాక్ట్ స్టేట్ (contract state) అనేది నిజమైన మూలం (source of truth). మీ అప్లికేషన్ దానిని ఇతర అప్లికేషన్ల మాదిరిగానే చదువుతుంది. ఇక్కడ ఎటువంటి ప్రత్యేకమైన (privileged) API టైర్ ఉండదు.

కోడ్ చాలా సరళంగా ఉంటుంది

@midnames/sdk ప్రధాన పనులన్నింటినీ నిర్వహిస్తుంది. ఒక డొమైన్‌ను అడ్రస్ మరియు ప్రొఫైల్‌గా రిజాల్వ్ చేయడానికి సరిగ్గా రెండు లైన్లు సరిపోతాయి:

const provider = createDefaultProvider({ networkId: "mainnet" });
const result = await resolveDomain(provider, "tomin.night");

అంతే! ప్రొవైడర్ నెట్‌వర్క్‌ను టార్గెట్ చేస్తుంది మరియు రిజాల్వర్ కాంట్రాక్ట్‌తో మాట్లాడుతుంది. SDK ఒక రిజల్ట్ ఆబ్జెక్ట్‌ను తిరిగి ఇస్తుంది, అందులో సక్సెస్ ఫ్లాగ్ (success flag) ఉంటుంది. ఒకవేళ డొమైన్ లేకపోతే, RPC ఫెయిల్యూర్ల కోసం మీరు క్లిష్టమైన ఎర్రర్ హ్యాండ్లింగ్ లేదా try-catch బ్లాక్‌లను ఉపయోగించాల్సిన అవసరం లేదు. అక్కడ ఏమీ లేదని SDK మీకు స్పష్టంగా చెబుతుంది. ఇది UIలను నిర్మించడాన్ని చాలా సులభతరం చేస్తుంది. ఫెయిల్యూర్ అనేది పేరు లేకపోవడం వల్ల జరిగిందా లేదా నోడ్ పనిచేయకపోవడం వల్ల జరిగిందా అని ఊహించాల్సిన అవసరం లేకుండా, మీరు సక్సెస్ ఫ్లాగ్‌ను బట్టి “not found” స్టేట్‌ను చూపించవచ్చు.

మీకు తిరిగి ఏమి లభిస్తుంది

లొకేషన్ (lookup) విజయవంతమైనప్పుడు, అందులోని పేలోడ్‌లో రెండు ముఖ్యమైన అంశాలు ఉంటాయి.

Target అనేది డొమైన్ సూచించే వాలెట్ అడ్రస్. ఇది దీని యొక్క ప్రధాన ఉపయోగం. ఇది ఒక పొడవైన hex అడ్రస్‌ను మనుషులు చదవగలిగేలా, టైప్ చేయగలిగేలా మరియు గుర్తుంచుకోగలిగేలా మారుస్తుంది.

Fields ప్రొఫైల్ వివరాలను కలిగి ఉంటాయి. యజమాని డొమైన్‌కు జత చేసిన సోషల్ లింక్‌లు, అవతార్‌లు, టెక్స్ట్ రికార్డులు ఇలా ఏదైనా ఈ స్ట్రక్చర్‌లో ఉంటాయి. ఈ ఫీల్డ్‌లు ఏదో ఒక కంపెనీ యొక్క MongoDB క్లస్టర్‌లో నిల్వ చేయబడవు. ఇవి కాంట్రాక్ట్ స్టేట్‌లోని ఫీల్డ్‌లు, అంటే రిజిస్ట్రీని ఎలా చదవాలో తెలిసిన ఏ అప్లికేషన్ అయినా అదే ప్రొఫైల్‌ను చూపించగలదు. దీనికి డేటాబేస్ సింక్ (database sync) అవసరం లేదు.

నన్ను నెమ్మదింపజేసిన రెండు చిక్కులు

ఈ బిల్డ్ ప్రక్రియ అంతా కేవలం రెండు లైన్లు మరియు ఒక సక్సెస్ ఫ్లాగ్‌తో ముగిసిపోలేదు. మీరు వీటిని మళ్ళీ ఎదుర్కోకుండా ఉండటానికి, నేను gặp ఎదురైన రెండు నిర్దిష్టమైన అడ్డంకులను ఇక్కడ వివరిస్తున్నాను.

నెట్‌వర్క్ మిస్‌మ్యాచ్ (Network Mismatch)

SDK, mainnet మరియు preprod రెండింటినీ సపోర్ట్ చేస్తుంది. "డొమైన్ లేదు" అని వస్తున్న ఎర్రర్‌ను డీబగ్ చేయడానికి నేను చాలా సమయం వృథా చేశాను. పేరు సరిగ్గానే ఉంది. కోడ్ కూడా సరిగ్గానే ఉంది. ప్రొవైడర్ కూడా రన్ అవుతోంది. అసలు సమస్య ఏమిటంటే, డొమైన్ mainnetలో రిజిస్టర్ చేయబడి ఉండగా, నా స్క్రిప్ట్ preprodని క్వెరీ చేస్తోంది. అది డొమైన్ లేనట్లుగా ఎర్రర్‌ను చూపించింది, కానీ నిజానికి అది నెట్‌వర్క్ కాంటెక్స్ట్ (network context) లేకపోవడం వల్ల జరిగింది.

మీరు ఒక పేరును రిజాల్వ్ చేస్తున్నప్పుడు ఫెయిల్యూర్ వస్తుంటే, వేరే దేనినైనా డీబగ్ చేసే ముందు ప్రొవైడర్ సెట్టింగ్‌లను తనిఖీ చేయండి. మీ networkId, డొమైన్ నిజంగా మిల్ట్ (mint) చేయబడిన నెట్‌వర్క్‌తో సరిపోలుతుందో లేదో చూసుకోండి. ఇది వెనక్కి తిరిగి చూసుకుంటే చాలా స్పష్టంగా అనిపించే తప్పు, కానీ కాంట్రాక్ట్ లాజిక్‌లోనే సమస్య ఉందని అనుకుంటున్నప్పుడు దీనిని గుర్తించడం నిజంగా కష్టం.

సీరియలైజేషన్ ఇబ్బందులు (Serialization Pain)

SDK నుండి వచ్చే డేటా సాధారణ JavaScript కాదు. ఇందులో BigInt విలువలు మరియు Map ఆబ్జెక్ట్‌లు ఉంటాయి. మీరు దానిని నేరుగా బ్రౌజర్‌కు పంపడానికి JSON.stringifyలోకి పంపాలని ప్రయత్నిస్తే, అది ఎర్రర్‌ను ఇస్తుంది లేదా డేటాను సైలెంట్‌గా వదిలేస్తుంది. BigIntకి నేరుగా JSON రిప్రజెంటేషన్ లేదు, మరియు Map సాధారణ ఆబ్జెక్ట్‌ల వలె సీరియలైజ్ కాదు.

చివరికి నేను ఒక కస్టమ్ సీరియలైజర్‌ను రాయాల్సి వచ్చింది. ఇది రిజల్ట్ ఆబ్జెక్ట్‌ను పరిశీలించి, BigInt విలువలను స్ట్రింగ్స్‌గా మారుస్తుంది మరియు రెస్పాన్స్ సర్వర్ నుండి బయటకు వెళ్లే ముందు Map ఇన్‌స్టెన్స్‌లను సాధారణ ఆబ్జెక్ట్‌లుగా మారుస్తుంది. మీరు ఫ్రంటెండ్‌కు Midnight డేటాను అందించే APIని నిర్మిస్తుంటే, ఈ దశ కోసం ముందుగానే ప్లాన్ చేయండి. అది JavaScript కాబట్టి SDK అవుట్‌పుట్ వెంటనే ఫ్రంటెండ్-ఫ్రెండ్లీగా ఉంటుందని అనుకోవద్దు.

ఆర్కిటెక్చర్ (The Architecture)

నేను ఈ స్టాక్‌ను కావాలనే చాలా సరళంగా ఉంచాను. బ్యాకెండ్ అనేది Express రన్ అవుతున్న ఒక Node సర్వర్. ఇది @midnames/sdkని ఇంపోర్ట్ చేస్తుంది, రిజల్యూషన్ లాజిక్‌ను రన్ చేస్తుంది, సిరియలైజేషన్ ప్రక్రియలను నిర్వహిస్తుంది మరియు క్లీన్ JSONని అందిస్తుంది. ఫ్రంటెండ్ అనేది సాధారణ HTML మరియు vanilla JavaScript. ఎలాంటి బిల్డ్ స్టెప్ లేదు. ఎలాంటి ఫ్రేమ్‌వర్క్ లేదు. ఎలాంటి వాలెట్ అడాప్టర్ లేదు.

కొన్ని ఆచరణాత్మక కారణాల వల్ల, నేను SDKని బ్రౌజర్‌లో కాకుండా బ్యాకెండ్‌లో రన్ చేయడానికి ఎంచుకున్నాను. ఇది ప్రొవైడర్ కాన్ఫిగరేషన్‌ను క్లయింట్ నుండి దూరంగా ఉంచుతుంది, సిరియలైజేషన్ సమస్యలను పరిష్కరించడానికి నాకు ఒకే ఒక చోటును ఇస్తుంది, మరియు ఫ్రంటెండ్ కేవలం డేటాను ఫెచ్ చేసి రెండర్ చేస్తే సరిపోతుంది.

నన్ను అత్యంత ఆశ్చర్యపరిచిన విషయం ఏమిటంటే: పేరును రిజాల్వ్ చేయడం (resolving a name) అనేది ఒక పబ్లిక్ రీడ్ ఆపరేషన్. దీనికి వాలెట్ కనెక్షన్ అవసరం లేదు. సంతకం (signature) అవసరం లేదు. యూజర్ దేనితోనూ లాగిన్ అవ్వాల్సిన అవసరం లేదు. డొమైన్ ఉంటే, కాంట్రాక్ట్ స్టేట్ (contract state) అడిగే ఎవరికైనా కనిపిస్తుంది. ప్రతి ఇంటరాక్షన్ "connect wallet"తో మొదలయ్యే సాధారణ web3 ఫ్లో నుండి ఇది ఒక అర్థవంతమైన తేడా. ఒక పబ్లిక్ వెబ్‌సైట్‌ను చదవడం అనేది ఎలాగైతే అనుమతి లేకుండా (permissionless) సాధ్యమవుతుందో, Midnightలో ఐడెంటిటీని చదవడం కూడా అలాగే అనుమతి లేకుండా సాధ్యమవుతుంది.

అసలైన సారాంశం

ఈ వ్యూయర్‌ను నిర్మించడం ద్వారా, బ్లాక్‌చైన్ డెవలప్‌మెంట్‌లో కష్టమైన భాగం చాలా అరుదుగా బ్లాక్‌చైన్ మాత్రమే అని నాకు గుర్తుకు వచ్చింది. Midnight ఇప్పటికే కష్టమైన సమస్యను పరిష్కరించింది: ఒక సెంట్రల్ డేటాబేస్ లేకుండా ప్రజలు తమ పేరు మరియు ప్రొఫైల్‌ను సొంతం చేసుకునేలా చేయడం. ఒక బిల్డర్ దృక్కోణంలో, కష్టమైన భాగం నేను ఏ నెట్‌వర్క్‌ను ఉపయోగిస్తున్నానో గుర్తుంచుకోవడం మరియు డేటా టైప్‌లను క్లీన్ చేయడానికి ఒక హెల్పర్ ఫంక్షన్‌ను రాయడం మాత్రమే.

ఈ ప్రోటోకాల్ మీకు పోర్టబుల్ ఐడెంటిటీని (portable identity) అందిస్తుంది. డెవలపర్‌గా మీ పని కేవలం దానిని సరిగ్గా చదవడం మరియు యూజర్‌కు ఎలాంటి అంతరాయం కలగకుండా చూడటం మాత్రమే. ఆర్కిటెక్చర్‌ను సరళంగా ఉంచండి, చైన్-ఫేసింగ్ లాజిక్‌ను UI నుండి వేరు చేయండి, మరియు పబ్లిక్ రీడ్‌లను అవి ఎలా ఉంటాయో అలాగే చూడండి: అవి కేవలం ఒక డిస్ట్రిబ్యూటెడ్ లెడ్జర్‌పై ఉన్న సాధారణ డేటాబేస్ క్వెరీల వంటివి.

మీరు కోడ్‌ను చూడాలనుకుంటే లేదా స్వయంగా రన్ చేయాలనుకుంటే, పూర్తి సోర్స్ కోడ్ ఇక్కడ అందుబాటులో ఉంది: https://github.com/tomiin/midnames-profile-viewer.