ప్రధాన కంటెంట్‌కు దాటవేయి

web3 యాప్‌ల కోసం సర్వర్ కాంపోనెంట్‌లు మరియు ఏజెంట్‌లు

ఏజెంట్
సర్వర్
ఆఫ్‌చైన్
dapps
ప్రారంభ స్థాయి
ఓరి పోమెరాంట్జ్
15 జులై, 2024
7 నిమిషాల పఠనం

పరిచయం

చాలా సందర్భాలలో, వికేంద్రీకృత అప్లికేషన్ (dapp) సాఫ్ట్‌వేర్‌ను పంపిణీ చేయడానికి సర్వర్‌ను ఉపయోగిస్తుంది, కానీ అసలు పరస్పర చర్య అంతా క్లయింట్ (సాధారణంగా, వెబ్ బ్రౌజర్) మరియు బ్లాక్‌చైన్ మధ్య జరుగుతుంది.

Normal interaction between web server, client, and blockchain

అయినప్పటికీ, స్వతంత్రంగా నడిచే సర్వర్ కాంపోనెంట్‌ను కలిగి ఉండటం వల్ల అప్లికేషన్ ప్రయోజనం పొందే కొన్ని సందర్భాలు ఉన్నాయి. అటువంటి సర్వర్ ఈవెంట్‌లకు మరియు లావాదేవీలను జారీ చేయడం ద్వారా API వంటి ఇతర మూలాల నుండి వచ్చే అభ్యర్థనలకు ప్రతిస్పందించగలదు.

The interaction with the addition of a server

అటువంటి సర్వర్ నెరవేర్చగల అనేక పనులు ఉన్నాయి.

  • రహస్య స్థితిని కలిగి ఉండేది. గేమింగ్‌లో, గేమ్‌కు తెలిసిన మొత్తం సమాచారం ఆటగాళ్లకు అందుబాటులో ఉండకపోవడం తరచుగా ఉపయోగకరంగా ఉంటుంది. అయితే, బ్లాక్‌చైన్‌లో ఎలాంటి రహస్యాలు ఉండవు, బ్లాక్‌చైన్‌లో ఉన్న ఏ సమాచారాన్నైనా ఎవరైనా సులభంగా తెలుసుకోవచ్చు. కాబట్టి, గేమ్ స్థితిలో కొంత భాగాన్ని రహస్యంగా ఉంచాలంటే, దానిని మరెక్కడైనా నిల్వ చేయాలి (మరియు బహుశా ఆ స్థితి యొక్క ప్రభావాలను శూన్య-జ్ఞాన ప్రూఫ్‌లను ఉపయోగించి ధృవీకరించాలి).

  • కేంద్రీకృత ఆరకిల్. పందాలు తగినంత తక్కువగా ఉంటే, ఆన్‌లైన్‌లో కొంత సమాచారాన్ని చదివి, ఆపై దానిని చైన్‌లో పోస్ట్ చేసే బాహ్య సర్వర్ ఆరకిల్గా ఉపయోగించడానికి సరిపోతుంది.

  • ఏజెంట్. దాన్ని సక్రియం చేయడానికి లావాదేవీ లేకుండా బ్లాక్‌చైన్‌లో ఏమీ జరగదు. అవకాశం వచ్చినప్పుడు ఆర్బిట్రేజ్ వంటి చర్యలను చేయడానికి సర్వర్ వినియోగదారు తరపున పని చేస్తుంది.

నమూనా ప్రోగ్రామ్

మీరు GitHubలో (opens in a new tab) నమూనా సర్వర్‌ను చూడవచ్చు. ఈ సర్వర్ Hardhat యొక్క గ్రీటర్ యొక్క సవరించిన వెర్షన్ అయిన ఈ కాంట్రాక్ట్ (opens in a new tab) నుండి వచ్చే ఈవెంట్‌లను వింటుంది. గ్రీటింగ్ మార్చబడినప్పుడు, అది దానిని తిరిగి మారుస్తుంది.

దీన్ని రన్ చేయడానికి:

  1. రిపోజిటరీని క్లోన్ చేయండి.

    git clone https://github.com/qbzzt/20240715-server-component.git
    cd 20240715-server-component
    
  2. అవసరమైన ప్యాకేజీలను ఇన్‌స్టాల్ చేయండి. మీకు ఇదివరకే లేకపోతే, ముందుగా Nodeని ఇన్‌స్టాల్ చేయండి (opens in a new tab).

    npm install
    
  3. Holesky టెస్ట్‌నెట్‌లో ETH ఉన్న ఖాతా యొక్క ప్రైవేట్ కీని పేర్కొనడానికి .envని సవరించండి. మీకు Holeskyలో ETH లేకపోతే, మీరు ఈ ఫాసెట్‌ని ఉపయోగించవచ్చు (opens in a new tab).

    PRIVATE_KEY=0x <private key goes here>
    
  4. సర్వర్‌ను ప్రారంభించండి.

    npm start
    
  5. బ్లాక్ ఎక్స్‌ప్లోరర్ (opens in a new tab)కి వెళ్లి, ప్రైవేట్ కీ ఉన్న చిరునామా కాకుండా వేరే చిరునామాను ఉపయోగించి గ్రీటింగ్‌ను సవరించండి. గ్రీటింగ్ స్వయంచాలకంగా తిరిగి సవరించబడిందో లేదో చూడండి.

ఇది ఎలా పని చేస్తుంది?

సర్వర్ కాంపోనెంట్‌ను ఎలా వ్రాయాలో అర్థం చేసుకోవడానికి సులభమైన మార్గం నమూనాను లైన్ బై లైన్ పరిశీలించడమే.

src/app.ts

ప్రోగ్రామ్‌లో ఎక్కువ భాగం src/app.ts (opens in a new tab)లో ఉంటుంది.

అవసరమైన ఆబ్జెక్ట్‌లను సృష్టించడం
import {
  createPublicClient,
  createWalletClient,
  getContract,
  http,
  Address,
} from "viem"

ఇవి మనకు అవసరమైన Viem (opens in a new tab) ఎంటిటీలు, ఫంక్షన్‌లు మరియు Address రకం (opens in a new tab). ఈ సర్వర్ TypeScript (opens in a new tab)లో వ్రాయబడింది, ఇది JavaScriptకి పొడిగింపు, ఇది దానిని స్ట్రాంగ్లీ టైప్డ్ (opens in a new tab)గా చేస్తుంది.

import { privateKeyToAccount } from "viem/accounts"

ఈ ఫంక్షన్ (opens in a new tab) ప్రైవేట్ కీకి సంబంధించిన చిరునామాతో సహా వాలెట్ సమాచారాన్ని రూపొందించడానికి మమ్మల్ని అనుమతిస్తుంది.

import { holesky } from "viem/chains"

Viemలో బ్లాక్‌చైన్‌ను ఉపయోగించడానికి మీరు దాని నిర్వచనాన్ని దిగుమతి చేసుకోవాలి. ఈ సందర్భంలో, మేము Holesky (opens in a new tab) టెస్ట్ బ్లాక్‌చైన్‌కి కనెక్ట్ చేయాలనుకుంటున్నాము.

// .env లోని నిర్వచనాలను process.env కి మనం ఈ విధంగా జోడిస్తాము.
import * as dotenv from "dotenv"
dotenv.config()

మేము పర్యావరణంలోకి .envని ఈ విధంగా చదువుతాము. ప్రైవేట్ కీ కోసం మాకు ఇది అవసరం (తర్వాత చూడండి).

కాంట్రాక్ట్‌ను ఉపయోగించడానికి మాకు దాని చిరునామా మరియు దాని కోసం అవసరం. మేము ఇక్కడ రెండింటినీ అందిస్తాము.

JavaScriptలో (మరియు అందువల్ల TypeScriptలో) మీరు స్థిరాంకానికి కొత్త విలువను కేటాయించలేరు, కానీ మీరు అందులో నిల్వ చేయబడిన ఆబ్జెక్ట్‌ను సవరించ_గలరు_. as const ప్రత్యయాన్ని ఉపయోగించడం ద్వారా మేము జాబితా స్థిరంగా ఉందని మరియు మార్చబడదని TypeScriptకి చెబుతున్నాము.

const publicClient = createPublicClient({
  chain: holesky,
  transport: http(),
})

Viem పబ్లిక్ క్లయింట్‌ (opens in a new tab)ను సృష్టించండి. పబ్లిక్ క్లయింట్‌లకు జోడించబడిన ప్రైవేట్ కీ ఉండదు, కాబట్టి లావాదేవీలను పంపలేరు. వారు view ఫంక్షన్‌ల (opens in a new tab)ను కాల్ చేయవచ్చు, ఖాతా బ్యాలెన్స్‌లను చదవవచ్చు మొదలైనవి.

const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`)

పర్యావరణ వేరియబుల్స్ process.env (opens in a new tab)లో అందుబాటులో ఉన్నాయి. అయితే, TypeScript స్ట్రాంగ్లీ టైప్ చేయబడింది. పర్యావరణ వేరియబుల్ ఏదైనా స్ట్రింగ్ కావచ్చు లేదా ఖాళీగా ఉండవచ్చు, కాబట్టి పర్యావరణ వేరియబుల్ రకం string | undefined. అయితే, Viemలో కీ 0x${string}గా నిర్వచించబడింది (0x తర్వాత స్ట్రింగ్). ఇక్కడ మేము PRIVATE_KEY పర్యావరణ వేరియబుల్ ఆ రకానికి చెందినదని TypeScriptకి చెబుతాము. అది కాకపోతే, మనకు రన్‌టైమ్ ఎర్రర్ వస్తుంది.

ఆ తర్వాత privateKeyToAccount (opens in a new tab) ఫంక్షన్ పూర్తి ఖాతా ఆబ్జెక్ట్‌ను సృష్టించడానికి ఈ ప్రైవేట్ కీని ఉపయోగిస్తుంది.

const walletClient = createWalletClient({
  account,
  chain: holesky,
  transport: http(),
})

తరువాత, మేము వాలెట్ క్లయింట్‌ (opens in a new tab)ను సృష్టించడానికి ఖాతా ఆబ్జెక్ట్‌ను ఉపయోగిస్తాము. ఈ క్లయింట్‌కు ప్రైవేట్ కీ మరియు చిరునామా ఉన్నాయి, కాబట్టి దీనిని లావాదేవీలను పంపడానికి ఉపయోగించవచ్చు.

const greeter = getContract({
  address: greeterAddress,
  abi: greeterABI,
  client: { public: publicClient, wallet: walletClient },
})

ఇప్పుడు మనకు అవసరమైనవన్నీ ఉన్నాయి కాబట్టి, చివరకు మనం కాంట్రాక్ట్ ఇన్‌స్టాన్స్‌ (opens in a new tab)ను సృష్టించవచ్చు. ఆన్‌చైన్ కాంట్రాక్ట్‌తో కమ్యూనికేట్ చేయడానికి మేము ఈ కాంట్రాక్ట్ ఇన్‌స్టాన్స్‌ను ఉపయోగిస్తాము.

బ్లాక్‌చైన్ నుండి చదవడం
console.log(`Current greeting:`, await greeter.read.greet())

కేవలం చదవడానికి మాత్రమే ఉన్న కాంట్రాక్ట్ ఫంక్షన్‌లు (view (opens in a new tab) మరియు pure (opens in a new tab)) read కింద అందుబాటులో ఉన్నాయి. ఈ సందర్భంలో, గ్రీటింగ్‌ను అందించే greet (opens in a new tab) ఫంక్షన్‌ను యాక్సెస్ చేయడానికి మేము దీన్ని ఉపయోగిస్తాము.

JavaScript సింగిల్-థ్రెడ్ చేయబడింది, కాబట్టి మనం ఎక్కువసేపు నడిచే ప్రాసెస్‌ను ప్రారంభించినప్పుడు మనం దానిని అసమకాలికంగా (asynchronously) చేస్తామని పేర్కొనాలి (opens in a new tab). బ్లాక్‌చైన్‌ను కాల్ చేయడానికి, కేవలం చదివే ఆపరేషన్ కోసం కూడా, కంప్యూటర్ మరియు బ్లాక్‌చైన్ నోడ్ మధ్య రౌండ్-ట్రిప్ అవసరం. ఫలితం కోసం కోడ్ await చేయాలని మేము ఇక్కడ పేర్కొనడానికి అదే కారణం.

ఇది ఎలా పని చేస్తుందో తెలుసుకోవాలనే ఆసక్తి మీకు ఉంటే, మీరు దాని గురించి ఇక్కడ చదవవచ్చు (opens in a new tab), కానీ ఆచరణాత్మకంగా మీరు తెలుసుకోవలసినది ఏమిటంటే, ఎక్కువ సమయం తీసుకునే ఆపరేషన్‌ను మీరు ప్రారంభిస్తే ఫలితాల కోసం మీరు await చేయాలి మరియు ఇలా చేసే ఏదైనా ఫంక్షన్‌ను asyncగా ప్రకటించాలి.

లావాదేవీలను జారీ చేయడం
const setGreeting = async (greeting: string): Promise<any> => {

గ్రీటింగ్‌ను మార్చే లావాదేవీని జారీ చేయడానికి మీరు కాల్ చేసే ఫంక్షన్ ఇది. ఇది సుదీర్ఘమైన ఆపరేషన్ కాబట్టి, ఫంక్షన్ asyncగా ప్రకటించబడింది. అంతర్గత అమలు కారణంగా, ఏదైనా async ఫంక్షన్ Promise ఆబ్జెక్ట్‌ను అందించాలి. ఈ సందర్భంలో, Promise<any> అంటే Promiseలో ఖచ్చితంగా ఏమి అందించబడుతుందో మేము పేర్కొనము.

const txHash = await greeter.write.setGreeting([greeting])

కాంట్రాక్ట్ ఇన్‌స్టాన్స్ యొక్క write ఫీల్డ్ బ్లాక్‌చైన్ స్థితికి వ్రాసే అన్ని ఫంక్షన్‌లను కలిగి ఉంటుంది (లావాదేవీని పంపాల్సినవి), ఉదాహరణకు setGreeting (opens in a new tab). పారామితులు ఏవైనా ఉంటే, అవి జాబితాగా అందించబడతాయి మరియు ఫంక్షన్ లావాదేవీ యొక్క హాష్‌ను అందిస్తుంది.

    console.log(`Working on a fix, see https://eth-holesky.blockscout.com/tx/${txHash}`)

    return txHash
}

లావాదేవీ యొక్క హాష్‌ను నివేదించండి (దానిని వీక్షించడానికి బ్లాక్ ఎక్స్‌ప్లోరర్‌కి URLలో భాగంగా) మరియు దానిని తిరిగి ఇవ్వండి.

ఈవెంట్‌లకు ప్రతిస్పందించడం
greeter.watchEvent.SetGreeting({

ఈవెంట్ వెలువడినప్పుడు ఫంక్షన్ రన్ కావాలని పేర్కొనడానికి watchEvent ఫంక్షన్ (opens in a new tab) మిమ్మల్ని అనుమతిస్తుంది. మీరు ఒక రకమైన ఈవెంట్ గురించి మాత్రమే శ్రద్ధ వహిస్తే (ఈ సందర్భంలో, SetGreeting), ఆ ఈవెంట్ రకానికి మిమ్మల్ని మీరు పరిమితం చేసుకోవడానికి ఈ సింటాక్స్‌ను ఉపయోగించవచ్చు.

    onLogs: logs => {

లాగ్ ఎంట్రీలు ఉన్నప్పుడు onLogs ఫంక్షన్ కాల్ చేయబడుతుంది. ఎథీరియంలో "లాగ్" మరియు "ఈవెంట్" సాధారణంగా పరస్పరం మార్చుకోదగినవి.

console.log(
  `Address ${logs[0].args.sender} changed the greeting to ${logs[0].args.greeting}`
)

బహుళ ఈవెంట్‌లు ఉండవచ్చు, కానీ సరళత కోసం మేము మొదటి దాని గురించి మాత్రమే శ్రద్ధ వహిస్తాము. logs[0].args అనేవి ఈవెంట్ యొక్క ఆర్గ్యుమెంట్‌లు, ఈ సందర్భంలో sender మరియు greeting.

        if (logs[0].args.sender != account.address)
            setGreeting(`${account.address} insists on it being Hello!`)
    }
})

పంపినవారు ఈ సర్వర్ కాకపోతే, గ్రీటింగ్‌ను మార్చడానికి setGreetingని ఉపయోగించండి.

package.json

ఈ ఫైల్ (opens in a new tab) Node.js (opens in a new tab) కాన్ఫిగరేషన్‌ను నియంత్రిస్తుంది. ఈ కథనం ముఖ్యమైన నిర్వచనాలను మాత్రమే వివరిస్తుంది.

{
  "main": "dist/index.js",

ఏ JavaScript ఫైల్‌ను రన్ చేయాలో ఈ నిర్వచనం నిర్దేశిస్తుంది.

  "scripts": {
    "start": "tsc && node dist/app.js",
  },

స్క్రిప్ట్‌లు వివిధ అప్లికేషన్ చర్యలు. ఈ సందర్భంలో, మన వద్ద ఉన్న ఏకైక స్క్రిప్ట్ start, ఇది కంపైల్ చేసి ఆపై సర్వర్‌ను రన్ చేస్తుంది. tsc కమాండ్ typescript ప్యాకేజీలో భాగం మరియు TypeScriptని JavaScriptకి కంపైల్ చేస్తుంది. మీరు దీన్ని మాన్యువల్‌గా రన్ చేయాలనుకుంటే, ఇది node_modules/.binలో ఉంటుంది. రెండవ కమాండ్ సర్వర్‌ను రన్ చేస్తుంది.

  "type": "module",

బహుళ రకాల JavaScript నోడ్ అప్లికేషన్‌లు ఉన్నాయి. module రకం టాప్ లెవల్ కోడ్‌లో awaitని కలిగి ఉండటానికి మమ్మల్ని అనుమతిస్తుంది, మీరు నెమ్మదిగా (మరియు అసమకాలికంగా) ఆపరేషన్‌లు చేసినప్పుడు ఇది ముఖ్యం.

  "devDependencies": {
    "@types/node": "^20.14.2",
    "typescript": "^5.4.5"
  },

ఇవి డెవలప్‌మెంట్ కోసం మాత్రమే అవసరమైన ప్యాకేజీలు. ఇక్కడ మాకు typescript అవసరం మరియు మేము దానిని Node.jsతో ఉపయోగిస్తున్నందున, మేము process వంటి నోడ్ వేరియబుల్స్ మరియు ఆబ్జెక్ట్‌ల రకాలను కూడా పొందుతున్నాము. ^<version> సంజ్ఞామానం (opens in a new tab) అంటే ఆ వెర్షన్ లేదా బ్రేకింగ్ మార్పులు లేని అధిక వెర్షన్ అని అర్థం. వెర్షన్ నంబర్‌ల అర్థం గురించి మరింత సమాచారం కోసం ఇక్కడ (opens in a new tab) చూడండి.

  "dependencies": {
    "dotenv": "^16.4.5",
    "viem": "2.14.1"
  }
}

dist/app.jsని రన్ చేస్తున్నప్పుడు, రన్‌టైమ్‌లో అవసరమైన ప్యాకేజీలు ఇవి.

ముగింపు

మేము ఇక్కడ సృష్టించిన కేంద్రీకృత సర్వర్ దాని పనిని చేస్తుంది, అంటే వినియోగదారు కోసం ఏజెంట్‌గా వ్యవహరించడం. వికేంద్రీకృత అప్లికేషన్ (dapp) పని చేస్తూనే ఉండాలని కోరుకునే మరియు గ్యాస్ ఖర్చు చేయడానికి ఇష్టపడే ఎవరైనా తమ స్వంత చిరునామాతో సర్వర్ యొక్క కొత్త ఇన్‌స్టాన్స్‌ను రన్ చేయవచ్చు.

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

నా మరిన్ని పనుల కోసం ఇక్కడ చూడండి (opens in a new tab).