web3 செயலிகளுக்கான சர்வர் கூறுகள் மற்றும் முகவர்கள்
அறிமுகம்
பெரும்பாலான சந்தர்ப்பங்களில், ஒரு பரவலாக்கப்பட்ட செயலி மென்பொருளை விநியோகிக்க ஒரு சர்வரைப் பயன்படுத்துகிறது, ஆனால் அனைத்து உண்மையான தொடர்புகளும் கிளையண்டிற்கும் (பொதுவாக, இணைய உலாவி) பிளாக்செயினுக்கும் இடையே நிகழ்கின்றன.
இருப்பினும், சில சந்தர்ப்பங்களில் ஒரு செயலி சுயாதீனமாக இயங்கும் சர்வர் கூறுகளைக் கொண்டிருப்பதன் மூலம் பயனடையலாம். அத்தகைய சர்வர் நிகழ்வுகளுக்கும், API போன்ற பிற மூலங்களிலிருந்து வரும் கோரிக்கைகளுக்கும் பரிவர்த்தனைகளை வழங்குவதன் மூலம் பதிலளிக்க முடியும்.
அத்தகைய சர்வர் நிறைவேற்றக்கூடிய பல சாத்தியமான பணிகள் உள்ளன.
-
ரகசிய நிலையை வைத்திருப்பவர். கேமிங்கில், கேமுக்குத் தெரிந்த அனைத்து தகவல்களும் பிளேயர்களுக்குக் கிடைக்காமல் இருப்பது பெரும்பாலும் பயனுள்ளதாக இருக்கும். இருப்பினும், பிளாக்செயினில் எந்த ரகசியங்களும் இல்லை, பிளாக்செயினில் உள்ள எந்தவொரு தகவலையும் யார் வேண்டுமானாலும் எளிதாகக் கண்டுபிடிக்க முடியும். எனவே, கேம் நிலையின் ஒரு பகுதியை ரகசியமாக வைத்திருக்க வேண்டுமானால், அது வேறு எங்காவது சேமிக்கப்பட வேண்டும் (மேலும் அந்த நிலையின் விளைவுகளை ஜீரோ-நாலேஜ் ப்ரூஃப்களைப் பயன்படுத்தி சரிபார்க்கலாம்).
-
மையப்படுத்தப்பட்ட ஆரக்கிள். அபாயங்கள் போதுமான அளவு குறைவாக இருந்தால், ஆன்லைனில் சில தகவல்களைப் படித்து பின்னர் அதைச் சங்கிலியில் இடுகையிடும் வெளிப்புற சர்வர் ஒரு ஆரக்கிளாகப் பயன்படுத்த போதுமானதாக இருக்கலாம்.
-
முகவர் (Agent). பிளாக்செயினைச் செயல்படுத்த ஒரு பரிவர்த்தனை இல்லாமல் எதுவும் நடக்காது. வாய்ப்பு கிடைக்கும்போது ஆர்பிட்ரேஜ் போன்ற செயல்களைச் செய்ய ஒரு பயனரின் சார்பாக ஒரு சர்வர் செயல்பட முடியும்.
மாதிரி நிரல்
நீங்கள் ஒரு மாதிரி சர்வரை github இல் (opens in a new tab) பார்க்கலாம். இந்த சர்வர் Hardhat இன் Greeter இன் மாற்றியமைக்கப்பட்ட பதிப்பான இந்த ஒப்பந்தத்திலிருந்து (opens in a new tab) வரும் நிகழ்வுகளைக் கவனிக்கிறது. வாழ்த்து மாற்றப்படும்போது, அது அதை மீண்டும் பழையபடி மாற்றுகிறது.
இதை இயக்க:
-
ரெபோசிட்டரியை குளோன் செய்யவும்.
git clone https://github.com/qbzzt/20240715-server-component.git cd 20240715-server-component -
தேவையான பேக்கேஜ்களை நிறுவவும். உங்களிடம் ஏற்கனவே இல்லையென்றால், முதலில் Node ஐ நிறுவவும் (opens in a new tab).
npm install -
Holesky டெஸ்ட்நெட்டில் ETH உள்ள கணக்கின் தனிப்பட்ட திறவுகோலைக் குறிப்பிட
.envஐத் திருத்தவும். உங்களிடம் Holesky இல் ETH இல்லையென்றால், நீங்கள் இந்த ஃபாசெட்டைப் பயன்படுத்தலாம் (opens in a new tab).PRIVATE_KEY=0x <private key goes here> -
சர்வரைத் தொடங்கவும்.
npm start -
ஒரு பிளாக் எக்ஸ்ப்ளோரருக்குச் (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 இல் பிளாக்செயினைப் பயன்படுத்த, அதன் வரையறையை நீங்கள் இறக்குமதி செய்ய வேண்டும். இந்த நிலையில், நாங்கள் Holesky (opens in a new tab) சோதனை பிளாக்செயினுடன் இணைக்க விரும்புகிறோம்.
// .env இல் உள்ள வரையறைகளை process.env இல் நாம் இப்படித்தான் சேர்க்கிறோம்.
import * as dotenv from "dotenv"
dotenv.config()
இப்படித்தான் நாம் .env ஐ சூழலில் படிக்கிறோம். தனிப்பட்ட திறவுகோலுக்கு இது நமக்குத் தேவை (பின்னர் பார்க்கவும்).
const greeterAddress : Address = "0xB8f6460Dc30c44401Be26B0d6eD250873d8a50A6"
const greeterABI = [
{
"inputs": [
{
"internalType": "string",
"name": "_greeting",
"type": "string"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
.
.
.
{
"inputs": [
{
"internalType": "string",
"name": "_greeting",
"type": "string"
}
],
"name": "setGreeting",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
] as const
ஒரு ஒப்பந்தத்தைப் பயன்படுத்த, அதன் முகவரி மற்றும் அதற்கான நமக்குத் தேவை. இரண்டையும் இங்கே வழங்குகிறோம்.
JavaScript இல் (எனவே TypeScript இலும்) நீங்கள் ஒரு மாறிலிக்கு (constant) புதிய மதிப்பை ஒதுக்க முடியாது, ஆனால் அதில் சேமிக்கப்பட்டுள்ள ஆப்ஜெக்ட்டை நீங்கள் மாற்றலாம். as const என்ற பின்னொட்டைப் பயன்படுத்துவதன் மூலம், பட்டியல் மாறிலியானது மற்றும் மாற்றப்படக்கூடாது என்று TypeScript இடம் கூறுகிறோம்.
const publicClient = createPublicClient({
chain: holesky,
transport: http(),
})
ஒரு Viem பொது கிளையண்டை (public client) (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 ஐத் தொடர்ந்து ஒரு சரம்) என வரையறுக்கப்படுகிறது. இங்கே PRIVATE_KEY சுற்றுச்சூழல் மாறி அந்த வகையாக இருக்கும் என்று TypeScript இடம் கூறுகிறோம். அது இல்லையென்றால், நமக்கு ஒரு இயக்க நேரப் பிழை (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 },
})
இப்போது எங்களிடம் அனைத்து முன்நிபந்தனைகளும் இருப்பதால், இறுதியாக ஒரு ஒப்பந்த நிகழ்வை (contract instance) (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), அந்த நிகழ்வு வகைக்கு உங்களை மட்டுப்படுத்த இந்த தொடரியலைப் (syntax) பயன்படுத்தலாம்.
onLogs: logs => {
பதிவு உள்ளீடுகள் (log entries) இருக்கும்போது onLogs செயல்பாடு அழைக்கப்படுகிறது. Ethereum இல் "log" மற்றும் "event" ஆகியவை பொதுவாக ஒன்றுக்கொன்று மாற்றக்கூடியவை.
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 ஆகும், இது தொகுத்து (compiles) பின்னர் சர்வரை இயக்குகிறது. 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 ஐ இயக்கும்போது, இயக்க நேரத்தில் (runtime) தேவைப்படும் பேக்கேஜ்கள் இவை.
முடிவுரை
நாங்கள் இங்கே உருவாக்கிய மையப்படுத்தப்பட்ட சர்வர் அதன் வேலையைச் செய்கிறது, அதாவது ஒரு பயனருக்கான முகவராகச் செயல்படுகிறது. dapp தொடர்ந்து செயல்பட வேண்டும் என்று விரும்பும் மற்றும் எரிவாயுவை (gas) செலவழிக்கத் தயாராக இருக்கும் வேறு எவரும் தங்கள் சொந்த முகவரியுடன் சர்வரின் புதிய நிகழ்வை இயக்கலாம்.
இருப்பினும், மையப்படுத்தப்பட்ட சர்வரின் செயல்களை எளிதாகச் சரிபார்க்க முடிந்தால் மட்டுமே இது செயல்படும். மையப்படுத்தப்பட்ட சர்வரில் ஏதேனும் ரகசிய நிலைத் தகவல் இருந்தால் அல்லது கடினமான கணக்கீடுகளை இயக்கினால், அது செயலியைப் பயன்படுத்த நீங்கள் நம்ப வேண்டிய ஒரு மையப்படுத்தப்பட்ட நிறுவனமாகும், இதைத்தான் பிளாக்செயின்கள் தவிர்க்க முயற்சிக்கின்றன. எதிர்காலக் கட்டுரையில் இந்தப் சிக்கலைத் தீர்க்க ஜீரோ-நாலேஜ் ப்ரூஃப்களை எவ்வாறு பயன்படுத்துவது என்பதைக் காட்டத் திட்டமிட்டுள்ளேன்.
எனது கூடுதல் பணிகளுக்கு இங்கே பார்க்கவும் (opens in a new tab).
பக்கம் கடைசியாகப் புதுப்பிக்கப்பட்டது: 3 மார்ச், 2026