முக்கிய உள்ளடக்கத்திற்குச் செல்லவும்

web3 செயலிகளுக்கான சேவையகக் கூறுகள் மற்றும் முகவர்கள்

முகவர்
சேவையகம்
சங்கிலிக்கு-வெளியே
dapps
தொடக்கநிலை
ஓரி பொமரன்ட்ஸ்
15 ஜூலை, 2024
7 நிமிட வாசிப்பு

அறிமுகம்

பெரும்பாலான சந்தர்ப்பங்களில், ஒரு பரவலாக்கப்பட்ட செயலி (dapp) மென்பொருளை விநியோகிக்க ஒரு சேவையகத்தைப் பயன்படுத்துகிறது, ஆனால் உண்மையான தொடர்புகள் அனைத்தும் கிளையண்ட் (பொதுவாக, இணைய உலாவி) மற்றும் தொகுதிச்சங்கிலிக்கு இடையே நிகழ்கின்றன.

Normal interaction between web server, client, and blockchain

இருப்பினும், சில சந்தர்ப்பங்களில் ஒரு செயலி சுயாதீனமாக இயங்கும் சேவையகக் கூறைக் கொண்டிருப்பதன் மூலம் பயனடையலாம். அத்தகைய சேவையகம் நிகழ்வுகளுக்கும், API போன்ற பிற மூலங்களிலிருந்து வரும் கோரிக்கைகளுக்கும் பரிவர்த்தனைகளை வழங்குவதன் மூலம் பதிலளிக்க முடியும்.

The interaction with the addition of a server

அத்தகைய சேவையகம் நிறைவேற்றக்கூடிய பல சாத்தியமான பணிகள் உள்ளன.

  • ரகசிய நிலையை வைத்திருப்பவர். கேமிங்கில், விளையாட்டுக்குத் தெரிந்த அனைத்து தகவல்களும் வீரர்களுக்குக் கிடைக்காமல் இருப்பது பெரும்பாலும் பயனுள்ளதாக இருக்கும். இருப்பினும், தொகுதிச்சங்கிலியில் எந்த ரகசியங்களும் இல்லை, தொகுதிச்சங்கிலியில் உள்ள எந்தவொரு தகவலையும் யார் வேண்டுமானாலும் எளிதாகக் கண்டறியலாம். எனவே, விளையாட்டின் நிலையின் ஒரு பகுதியை ரகசியமாக வைத்திருக்க வேண்டுமானால், அது வேறு எங்காவது சேமிக்கப்பட வேண்டும் (மேலும் அந்த நிலையின் விளைவுகளை பூஜ்ய-அறிவு சான்றுகளைப் பயன்படுத்தி சரிபார்க்கலாம்).

  • மையப்படுத்தப்பட்ட தரவு வழங்கி. அபாயங்கள் போதுமான அளவு குறைவாக இருந்தால், ஆன்லைனில் சில தகவல்களைப் படித்து பின்னர் அதைச் சங்கிலியில் இடுகையிடும் வெளிப்புற சேவையகம் ஒரு தரவு வழங்கியாகப் பயன்படுத்த போதுமானதாக இருக்கலாம்.

  • முகவர். அதைச் செயல்படுத்த ஒரு பரிவர்த்தனை இல்லாமல் தொகுதிச்சங்கிலியில் எதுவும் நடக்காது. வாய்ப்பு கிடைக்கும்போது விலை வித்தியாசம் மூலம் லாபம் ஈட்டுதல் (arbitrage) போன்ற செயல்களைச் செய்ய ஒரு பயனரின் சார்பாக ஒரு சேவையகம் செயல்பட முடியும்.

மாதிரி நிரல்

நீங்கள் ஒரு மாதிரி சேவையகத்தை GitHub இல் (opens in a new tab) பார்க்கலாம். இந்த சேவையகம் Hardhat இன் Greeter இன் மாற்றியமைக்கப்பட்ட பதிப்பான இந்த ஒப்பந்தத்திலிருந்து (opens in a new tab) வரும் நிகழ்வுகளைக் கவனிக்கிறது. வாழ்த்து மாற்றப்படும்போது, அது அதை மீண்டும் பழையபடி மாற்றுகிறது.

இதை இயக்க:

  1. களஞ்சியத்தை (repository) குளோன் செய்யவும்.

    git clone https://github.com/qbzzt/20240715-server-component.git
    cd 20240715-server-component
    
  2. தேவையான தொகுப்புகளை நிறுவவும். உங்களிடம் அது ஏற்கனவே இல்லையென்றால், முதலில் Node ஐ நிறுவவும் (opens in a new tab).

    npm install
    
  3. ஹோல்ஸ்கி சோதனை வலையமைப்பில் ETH உள்ள ஒரு கணக்கின் தனிப்பட்ட திறவுகோலைக் குறிப்பிட .env ஐத் திருத்தவும். ஹோல்ஸ்கியில் உங்களிடம் 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 இன் நீட்டிப்பாகும், இது அதை வலுவாக தட்டச்சு செய்யப்பட்டதாக (strongly typed) (opens in a new tab) மாற்றுகிறது.

import { privateKeyToAccount } from "viem/accounts"

இந்தச் செயல்பாடு (opens in a new tab) ஒரு தனிப்பட்ட திறவுகோலுக்குரிய முகவரி உட்பட பணப்பைத் தகவலை உருவாக்க அனுமதிக்கிறது.

import { holesky } from "viem/chains"

Viem இல் ஒரு தொகுதிச்சங்கிலியைப் பயன்படுத்த, அதன் வரையறையை நீங்கள் இறக்குமதி செய்ய வேண்டும். இந்த நிலையில், நாங்கள் ஹோல்ஸ்கி (opens in a new tab) சோதனைத் தொகுதிச்சங்கிலியுடன் இணைக்க விரும்புகிறோம்.

// .env இல் உள்ள வரையறைகளை process.env இல் நாம் இவ்வாறுதான் சேர்க்கிறோம்.
import * as dotenv from "dotenv"
dotenv.config()

இப்படித்தான் நாம் .env ஐச் சூழலில் படிக்கிறோம். தனிப்பட்ட திறவுகோலுக்கு இது நமக்குத் தேவை (பின்னர் பார்க்கவும்).

ஒரு ஒப்பந்தத்தைப் பயன்படுத்த, அதன் முகவரி மற்றும் அதற்கான நமக்குத் தேவை. இரண்டையும் இங்கே வழங்குகிறோம்.

JavaScript இல் (எனவே TypeScript இலும்) நீங்கள் ஒரு மாறிலிக்கு (constant) புதிய மதிப்பை ஒதுக்க முடியாது, ஆனால் அதில் சேமிக்கப்பட்டுள்ள பொருளை நீங்கள் மாற்றலாம். 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) அல்லது காலியாகவோ இருக்கலாம், எனவே ஒரு சூழல் மாறிக்கான வகை string | undefined ஆகும். இருப்பினும், Viem இல் ஒரு திறவுகோல் 0x${string} (0x ஐத் தொடர்ந்து ஒரு சரம்) என வரையறுக்கப்படுகிறது. இங்கே நாம் TypeScript இடம் PRIVATE_KEY சூழல் மாறி அந்த வகையாக இருக்கும் என்று கூறுகிறோம். அது இல்லையென்றால், நமக்கு ஒரு இயக்க நேரப் பிழை (runtime error) கிடைக்கும்.

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 ஒற்றை-நூல் (single-threaded) கொண்டது, எனவே நீண்ட நேரம் இயங்கும் ஒரு செயல்முறையைத் தொடங்கும்போது, அதை ஒத்திசைவற்ற முறையில் (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 என்பவை நிகழ்வின் வாதங்கள் (arguments), இந்த நிலையில் 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).