मुख्य सामग्री पर जाएँ

आपके अनुबंध के लिए एक यूज़र इंटरफ़ेस बनाना

TypeScript
react
vite
wagmi
frontend
शुरआती
ओरी पोमेरेंट्ज़
1 नवंबर 2023
17 मिनट का पठन

आपको एथेरियम इकोसिस्टम में एक ऐसी सुविधा मिली जिसकी हमें आवश्यकता है। आपने इसे लागू करने के लिए स्मार्ट अनुबंध लिखे, और शायद कुछ संबंधित कोड भी जो ऑफ-चेन चलता है। यह बहुत बढ़िया है! दुर्भाग्य से, यूज़र इंटरफ़ेस के बिना आपके पास कोई यूज़र नहीं होगा, और पिछली बार जब आपने कोई वेबसाइट लिखी थी तो लोग डायल-अप मोडेम का उपयोग करते थे और जावास्क्रिप्ट नया था।

यह लेख आपके लिए है। मैं मानता हूँ कि आप प्रोग्रामिंग जानते हैं, और शायद थोड़ी जावास्क्रिप्ट और HTML भी, लेकिन आपके यूज़र इंटरफ़ेस कौशल पुराने और आउट ऑफ डेट हैं। हम साथ मिलकर एक सरल आधुनिक एप्लिकेशन पर काम करेंगे ताकि आप देख सकें कि इन दिनों यह कैसे किया जाता है।

यह क्यों महत्वपूर्ण है

सिद्धांत रूप में, आप लोगों को अपने अनुबंधों के साथ इंटरैक्ट करने के लिए ईथरस्कैन (opens in a new tab) या ब्लॉकस्काउट (opens in a new tab) का उपयोग करा सकते हैं। यह अनुभवी Ethereans के लिए बहुत अच्छा होगा। लेकिन हम एक और अरब लोगों (opens in a new tab) की सेवा करने की कोशिश कर रहे हैं। यह एक बेहतरीन यूज़र अनुभव के बिना नहीं होगा, और एक अनुकूल यूज़र इंटरफ़ेस इसका एक बड़ा हिस्सा है।

Greeter एप्लिकेशन

एक आधुनिक UI कैसे काम करता है इसके पीछे बहुत सारे सिद्धांत हैं, और बहुत सारी अच्छी साइटें (opens in a new tab) हैं जो इसे समझाती हैं (opens in a new tab)। उन साइटों द्वारा किए गए अच्छे काम को दोहराने के बजाय, मैं यह मानूंगा कि आप करके सीखना पसंद करते हैं और एक ऐसे एप्लिकेशन से शुरू करना चाहते हैं जिसके साथ आप खेल सकते हैं। चीजों को पूरा करने के लिए आपको अभी भी सिद्धांत की आवश्यकता है, और हम उस पर पहुँचेंगे - हम बस स्रोत फ़ाइल दर स्रोत फ़ाइल जाएँगे, और जैसे-जैसे हम उन तक पहुँचेंगे, चीजों पर चर्चा करेंगे।

इंस्टॉलेशन

  1. यदि आवश्यक हो, तो अपने वॉलेट में होलस्की ब्लॉकचेन (opens in a new tab) जोड़ें और टेस्ट ETH (opens in a new tab) प्राप्त करें।

  2. github रिपॉजिटरी को क्लोन करें।

    1git clone https://github.com/qbzzt/20230801-modern-ui.git
  3. आवश्यक पैकेज इंस्टॉल करें।

    1cd 20230801-modern-ui
    2pnpm install
  4. एप्लिकेशन शुरू करें।

    1pnpm dev
  5. एप्लिकेशन द्वारा दिखाए गए URL पर ब्राउज़ करें। अधिकांश मामलों में, वह http://localhost:5173/ (opens in a new tab) है।

  6. आप अनुबंध स्रोत कोड, हार्डहैट के Greeter का थोड़ा संशोधित संस्करण, एक ब्लॉकचेन एक्सप्लोरर पर (opens in a new tab) देख सकते हैं।

फ़ाइल वॉक थ्रू

index.html

यह फ़ाइल मानक HTML बॉयलरप्लेट है, सिवाय इस लाइन के, जो स्क्रिप्ट फ़ाइल को आयात करती है।

1<script type="module" src="/src/main.tsx"></script>

src/main.tsx

फ़ाइल एक्सटेंशन हमें बताता है कि यह फ़ाइल टाइपस्क्रिप्ट (opens in a new tab) में लिखा गया एक रिएक्ट घटक (opens in a new tab) है, जो जावास्क्रिप्ट का एक एक्सटेंशन है जो टाइप चेकिंग (opens in a new tab) का समर्थन करता है। टाइपस्क्रिप्ट को जावास्क्रिप्ट में संकलित किया जाता है, इसलिए हम इसे क्लाइंट-साइड निष्पादन के लिए उपयोग कर सकते हैं।

1import '@rainbow-me/rainbowkit/styles.css'
2import { RainbowKitProvider } from '@rainbow-me/rainbowkit'
3import * as React from 'react'
4import * as ReactDOM from 'react-dom/client'
5import { WagmiConfig } from 'wagmi'
6import { chains, config } from './wagmi'

हमें जिस लाइब्रेरी कोड की आवश्यकता है उसे आयात करें।

1import { App } from './App'

उस रिएक्ट घटक को आयात करें जो एप्लिकेशन को लागू करता है (नीचे देखें)।

1ReactDOM.createRoot(document.getElementById('root')!).render(

रूट रिएक्ट घटक बनाएँ। render का पैरामीटर JSX (opens in a new tab) है, जो एक एक्सटेंशन भाषा है जो HTML और जावास्क्रिप्ट/टाइपस्क्रिप्ट दोनों का उपयोग करती है। यहाँ विस्मयादिबोधक बिंदु टाइपस्क्रिप्ट घटक को बताता है: "आप नहीं जानते कि document.getElementById('root') ReactDOM.createRoot के लिए एक वैध पैरामीटर होगा, लेकिन चिंता न करें - मैं डिवेलपर हूँ और मैं आपको बता रहा हूँ कि यह होगा"।

1 <React.StrictMode>

एप्लिकेशन एक React.StrictMode घटक (opens in a new tab) के अंदर जा रहा है। यह घटक रिएक्ट लाइब्रेरी को अतिरिक्त डिबगिंग जाँचें डालने के लिए कहता है, जो विकास के दौरान उपयोगी है।

1 <WagmiConfig config={config}>

एप्लिकेशन एक WagmiConfig घटक (opens in a new tab) के अंदर भी है। wagmi (we are going to make it) लाइब्रेरी (opens in a new tab) रिएक्ट UI परिभाषाओं को एथेरियम विकेंद्रीकृत अनुप्रयोग लिखने के लिए viem लाइब्रेरी (opens in a new tab) से जोड़ती है।

1 <RainbowKitProvider chains={chains}>

और अंत में, एक RainbowKitProvider घटक (opens in a new tab)। यह घटक लॉग ऑन करने और वॉलेट और एप्लिकेशन के बीच संचार को संभालता है।

1 <App />

अब हमारे पास एप्लिकेशन के लिए घटक हो सकता है, जो वास्तव में UI को लागू करता है। घटक के अंत में /> रिएक्ट को बताता है कि इस घटक के अंदर कोई परिभाषा नहीं है, जैसा कि XML मानक के अनुसार है।

1 </RainbowKitProvider>
2 </WagmiConfig>
3 </React.StrictMode>,
4)

बेशक, हमें अन्य घटकों को बंद करना होगा।

src/App.tsx

1import { ConnectButton } from '@rainbow-me/rainbowkit'
2import { useAccount } from 'wagmi'
3import { Greeter } from './components/Greeter'
4
5export function App() {

यह एक रिएक्ट घटक बनाने का मानक तरीका है - एक फ़ंक्शन को परिभाषित करें जिसे हर बार रेंडर करने की आवश्यकता होने पर कॉल किया जाता है। इस फ़ंक्शन में आम तौर पर शीर्ष पर कुछ टाइपस्क्रिप्ट या जावास्क्रिप्ट कोड होता है, जिसके बाद एक return कथन होता है जो JSX कोड लौटाता है।

1 const { isConnected } = useAccount()

यहां हम यह जांचने के लिए useAccount (opens in a new tab) का उपयोग करते हैं कि हम वॉलेट के माध्यम से ब्लॉकचेन से जुड़े हैं या नहीं।

परंपरा के अनुसार, रिएक्ट में use... नामक फ़ंक्शन हुक (opens in a new tab) होते हैं जो किसी प्रकार का डेटा लौटाते हैं। जब आप ऐसे हुक का उपयोग करते हैं, तो न केवल आपके घटक को डेटा मिलता है, बल्कि जब वह डेटा बदलता है तो घटक को अद्यतन जानकारी के साथ फिर से प्रस्तुत किया जाता है।

1 return (
2 <>

एक रिएक्ट घटक के JSX को एक घटक लौटाना होता है। जब हमारे पास कई घटक होते हैं और हमारे पास कुछ भी नहीं होता है जो "स्वाभाविक रूप से" लपेटता है, तो हम एक खाली घटक (<> ... और </>) का उपयोग करते हैं उन्हें एक ही घटक में बनाने के लिए।

1 <h1>Greeter</h1>
2 <ConnectButton />

हम रेनबोकिट से ConnectButton घटक (opens in a new tab) प्राप्त करते हैं। जब हम कनेक्ट नहीं होते हैं, तो यह हमें एक Connect Wallet बटन देता है जो एक मोडल खोलता है जो वॉलेट के बारे में बताता है और आपको यह चुनने देता है कि आप किसका उपयोग करते हैं। जब हम कनेक्ट होते हैं, तो यह हमारे द्वारा उपयोग किए जाने वाले ब्लॉकचेन, हमारे खाते का पता और हमारा ETH बैलेंस प्रदर्शित करता है। हम इन डिस्प्ले का उपयोग नेटवर्क स्विच करने या डिस्कनेक्ट करने के लिए कर सकते हैं।

1 {isConnected && (

जब हमें JSX में वास्तविक जावास्क्रिप्ट (या टाइपस्क्रिप्ट जिसे जावास्क्रिप्ट में संकलित किया जाएगा) डालने की आवश्यकता होती है, तो हम ब्रैकेट ({}) का उपयोग करते हैं।

a && b सिंटैक्स a ? के लिए छोटा है b : a (opens in a new tab) है। अर्थात्, यदि a सत्य है तो यह b का मूल्यांकन करता है और अन्यथा यह a का मूल्यांकन करता है (जो false, 0, आदि हो सकता है)। यह रिएक्ट को यह बताने का एक आसान तरीका है कि एक घटक केवल तभी प्रदर्शित किया जाना चाहिए जब कोई निश्चित शर्त पूरी हो।

इस मामले में, हम केवल यूज़र को Greeter दिखाना चाहते हैं यदि यूज़र ब्लॉकचेन से जुड़ा है।

1 <Greeter />
2 )}
3 </>
4 )
5}

src/components/Greeter.tsx

इस फ़ाइल में अधिकांश UI फ़ंक्शनैलिटी शामिल है। इसमें ऐसी परिभाषाएँ शामिल हैं जो सामान्य रूप से कई फ़ाइलों में होंगी, लेकिन चूँकि यह एक ट्यूटोरियल है, प्रोग्राम को पहली बार समझने में आसान होने के लिए अनुकूलित किया गया है, न कि प्रदर्शन या रखरखाव में आसानी के लिए।

1import { useState, ChangeEventHandler } from 'react'
2import { useNetwork,
3 useReadContract,
4 usePrepareContractWrite,
5 useContractWrite,
6 useContractEvent
7 } from 'wagmi'

हम इन लाइब्रेरी फ़ंक्शन का उपयोग करते हैं। फिर से, उन्हें नीचे समझाया गया है जहाँ उनका उपयोग किया जाता है।

1import { AddressType } from 'abitype'

abitype लाइब्रेरी (opens in a new tab) हमें विभिन्न एथेरियम डेटा प्रकारों के लिए टाइपस्क्रिप्ट परिभाषाएँ प्रदान करती है, जैसे कि AddressType (opens in a new tab)

1let greeterABI = [
2 .
3 .
4 .
5] as const // greeterABI

Greeter अनुबंध के लिए ABI। यदि आप एक ही समय में अनुबंध और UI विकसित कर रहे हैं, तो आप सामान्य रूप से उन्हें एक ही रिपॉजिटरी में रखेंगे और अपने एप्लिकेशन में एक फ़ाइल के रूप में सॉलिडिटी कंपाइलर द्वारा उत्पन्न ABI का उपयोग करेंगे। हालाँकि, यहाँ यह आवश्यक नहीं है क्योंकि अनुबंध पहले ही विकसित हो चुका है और बदलने वाला नहीं है।

1type AddressPerBlockchainType = {
2 [key: number]: AddressType
3}

टाइपस्क्रिप्ट दृढ़ता से टाइप किया गया है। हम इस परिभाषा का उपयोग उस पते को निर्दिष्ट करने के लिए करते हैं जिसमें Greeter अनुबंध विभिन्न चेनों पर तैनात है। की एक संख्या (chainId) है, और मान एक AddressType (एक पता) है।

1const contractAddrs: AddressPerBlockchainType = {
2 // Holesky
3 17000: '0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8',
4
5 // Sepolia
6 11155111: '0x7143d5c190F048C8d19fe325b748b081903E3BF0'
7}

दो समर्थित नेटवर्कों पर अनुबंध का पता: होलस्की (opens in a new tab) और सेपोलिया (opens in a new tab)

नोट: वास्तव में एक तीसरी परिभाषा है, Redstone होलस्की के लिए, इसे नीचे समझाया जाएगा।

1type ShowObjectAttrsType = {
2 name: string,
3 object: any
4}

इस प्रकार का उपयोग ShowObject घटक (बाद में समझाया गया) के पैरामीटर के रूप में किया जाता है। इसमें ऑब्जेक्ट का नाम और उसका मान शामिल है, जो डिबगिंग उद्देश्यों के लिए प्रदर्शित किए जाते हैं।

1type ShowGreetingAttrsType = {
2 greeting: string | undefined
3}

किसी भी समय हम या तो जान सकते हैं कि अभिवादन क्या है (क्योंकि हमने इसे ब्लॉकचेन से पढ़ा है) या नहीं जानते (क्योंकि हमें अभी तक यह प्राप्त नहीं हुआ है)। तो एक ऐसा प्रकार होना उपयोगी है जो या तो एक स्ट्रिंग हो सकता है या कुछ भी नहीं।

Greeter घटक
1const Greeter = () => {

अंत में, हम घटक को परिभाषित करते हैं।

1 const { chain } = useNetwork()

wagmi (opens in a new tab) के सौजन्य से, हम जिस चेन का उपयोग कर रहे हैं उसके बारे में जानकारी। क्योंकि यह एक हुक (use...) है, हर बार जब यह जानकारी बदलती है तो घटक फिर से तैयार हो जाता है।

1 const greeterAddr = chain && contractAddrs[chain.id]

Greeter अनुबंध का पता, जो चेन के अनुसार बदलता रहता है (और जो undefined होता है यदि हमारे पास चेन की जानकारी नहीं है या हम उस अनुबंध के बिना किसी चेन पर हैं)।

1 const readResults = useReadContract({
2 address: greeterAddr,
3 abi: greeterABI,
4 functionName: "greet" , // कोई तर्क नहीं
5 watch: true
6 })

useReadContract हुक (opens in a new tab) एक अनुबंध से जानकारी पढ़ता है। आप देख सकते हैं कि यह वास्तव में UI में readResults का विस्तार करके कौन सी जानकारी लौटाता है। इस मामले में हम चाहते हैं कि यह देखता रहे ताकि जब अभिवादन बदले तो हमें सूचित किया जा सके।

ध्यान दें: हम यह जानने के लिए setGreeting इवेंट्स (opens in a new tab) सुन सकते हैं कि अभिवादन कब बदलता है और उस तरह से अपडेट कर सकते हैं। हालाँकि, जबकि यह अधिक कुशल हो सकता है, यह सभी मामलों में लागू नहीं होगा। जब यूज़र एक अलग चेन पर स्विच करता है तो अभिवादन भी बदल जाता है, लेकिन उस बदलाव के साथ कोई इवेंट नहीं होता है। हमारे पास कोड का एक हिस्सा इवेंट्स के लिए सुन सकता है और दूसरा चेन परिवर्तनों की पहचान करने के लिए हो सकता है, लेकिन यह केवल watch पैरामीटर (opens in a new tab) सेट करने से अधिक जटिल होगा।

1 const [ newGreeting, setNewGreeting ] = useState("")

रिएक्ट का useState हुक (opens in a new tab) हमें एक स्टेट वेरिएबल निर्दिष्ट करने देता है, जिसका मान घटक के एक रेंडरिंग से दूसरे में बना रहता है। प्रारंभिक मान पैरामीटर है, इस मामले में खाली स्ट्रिंग।

useState हुक दो मानों वाली एक सूची लौटाता है:

  1. स्टेट वेरिएबल का वर्तमान मान।
  2. आवश्यकता पड़ने पर स्टेट वेरिएबल को संशोधित करने के लिए एक फ़ंक्शन। चूँकि यह एक हुक है, हर बार जब इसे कॉल किया जाता है तो घटक फिर से रेंडर होता है।

इस मामले में, हम उस नए अभिवादन के लिए एक स्टेट वेरिएबल का उपयोग कर रहे हैं जिसे यूज़र सेट करना चाहता है।

1 const greetingChange : ChangeEventHandler<HTMLInputElement> = (evt) =>
2 setNewGreeting(evt.target.value)

यह नए अभिवादन इनपुट फ़ील्ड के बदलने पर इवेंट हैंडलर है। प्रकार, ChangeEventHandler<HTMLInputElement> (opens in a new tab), निर्दिष्ट करता है कि यह एक HTML इनपुट तत्व के मान परिवर्तन के लिए हैंडलर है। <HTMLInputElement> भाग का उपयोग किया जाता है क्योंकि यह एक जेनेरिक प्रकार (opens in a new tab) है।

1 const preparedTx = usePrepareContractWrite({
2 address: greeterAddr,
3 abi: greeterABI,
4 functionName: 'setGreeting',
5 args: [ newGreeting ]
6 })
7 const workingTx = useContractWrite(preparedTx.config)

क्लाइंट के दृष्टिकोण से ब्लॉकचेन लेनदेन जमा करने की यह प्रक्रिया है:

  1. ब्लॉकचेन में एक नोड को eth_estimateGas (opens in a new tab) का उपयोग करके लेनदेन भेजें।
  2. नोड से प्रतिक्रिया की प्रतीक्षा करें।
  3. जब प्रतिक्रिया प्राप्त हो जाए, तो यूज़र से वॉलेट के माध्यम से लेनदेन पर हस्ताक्षर करने के लिए कहें। यह कदम नोड प्रतिक्रिया प्राप्त होने के बाद होना चाहिए क्योंकि यूज़र को उस पर हस्ताक्षर करने से पहले लेनदेन की गैस लागत दिखाई जाती है।
  4. यूज़र द्वारा स्वीकृति की प्रतीक्षा करें।
  5. लेनदेन फिर से भेजें, इस बार eth_sendRawTransaction (opens in a new tab) का उपयोग करके।

चरण 2 में संभवतः एक बोधगम्य समय लगेगा, जिसके दौरान यूज़र सोचेंगे कि क्या उनका कमांड वास्तव में यूज़र इंटरफ़ेस द्वारा प्राप्त किया गया था और उनसे पहले से ही लेनदेन पर हस्ताक्षर करने के लिए क्यों नहीं कहा जा रहा है। यह खराब यूज़र अनुभव (UX) बनाता है।

समाधान तैयारी हुक (opens in a new tab) का उपयोग करना है। हर बार जब कोई पैरामीटर बदलता है, तो तुरंत नोड को eth_estimateGas अनुरोध भेजें। फिर, जब यूज़र वास्तव में लेनदेन भेजना चाहता है (अभिवादन अपडेट करें दबाकर), तो गैस लागत ज्ञात होती है और यूज़र तुरंत वॉलेट पेज देख सकता है।

1 return (

अब हम अंत में वापसी के लिए वास्तविक HTML बना सकते हैं।

1 <>
2 <h2>Greeter</h2>
3 {
4 !readResults.isError && !readResults.isLoading &&
5 <ShowGreeting greeting={readResults.data} />
6 }
7 <hr />

एक ShowGreeting घटक बनाएँ (नीचे समझाया गया है), लेकिन केवल तभी जब अभिवादन ब्लॉकचेन से सफलतापूर्वक पढ़ा गया हो।

1 <input type="text"
2 value={newGreeting}
3 onChange={greetingChange}
4 />

यह इनपुट टेक्स्ट फ़ील्ड है जहाँ यूज़र एक नया अभिवादन सेट कर सकता है। हर बार जब यूज़र कोई की दबाता है, तो हम greetingChange को कॉल करते हैं जो setNewGreeting को कॉल करता है। चूंकि setNewGreeting useState हुक से आता है, यह Greeter घटक को फिर से प्रस्तुत करने का कारण बनता है। इसका मतलब है कि:

  • हमें नए अभिवादन का मान रखने के लिए value निर्दिष्ट करने की आवश्यकता है, क्योंकि अन्यथा यह डिफ़ॉल्ट, खाली स्ट्रिंग में वापस आ जाएगा।
  • usePrepareContractWrite को हर बार newGreeting बदलने पर कॉल किया जाता है, जिसका अर्थ है कि तैयार लेनदेन में हमेशा नवीनतम newGreeting होगा।
1 <button disabled={!workingTx.write}
2 onClick={workingTx.write}
3 >
4 अभिवादन अपडेट करें
5 </button>

यदि कोई workingTx.write नहीं है तो हम अभी भी अभिवादन अपडेट भेजने के लिए आवश्यक जानकारी की प्रतीक्षा कर रहे हैं, इसलिए बटन अक्षम है। यदि कोई workingTx.write मान है तो वह लेनदेन भेजने के लिए कॉल करने वाला फ़ंक्शन है।

1 <hr />
2 <ShowObject name="readResults" object={readResults} />
3 <ShowObject name="preparedTx" object={preparedTx} />
4 <ShowObject name="workingTx" object={workingTx} />
5 </>
6 )
7}

अंत में, यह देखने में आपकी मदद करने के लिए कि हम क्या कर रहे हैं, हमारे द्वारा उपयोग की जाने वाली तीन वस्तुओं को दिखाएँ:

  • readResults
  • preparedTx
  • workingTx
ShowGreeting घटक

यह घटक दिखाता है

1const ShowGreeting = (attrs : ShowGreetingAttrsType) => {

एक घटक फ़ंक्शन घटक के सभी विशेषताओं के साथ एक पैरामीटर प्राप्त करता है।

1 return <b>{attrs.greeting}</b>
2}
ShowObject घटक

सूचना उद्देश्यों के लिए, हम महत्वपूर्ण वस्तुओं को दिखाने के लिए ShowObject घटक का उपयोग करते हैं (अभिवादन पढ़ने के लिए readResults और हमारे द्वारा बनाए गए लेनदेन के लिए preparedTx और workingTx)।

1const ShowObject = (attrs: ShowObjectAttrsType ) => {
2 const keys = Object.keys(attrs.object)
3 const funs = keys.filter(k => typeof attrs.object[k] == "function")
4 return <>
5 <details>

हम सभी जानकारी के साथ UI को अव्यवस्थित नहीं करना चाहते हैं, इसलिए उन्हें देखने या बंद करना संभव बनाने के लिए, हम एक details (opens in a new tab) टैग का उपयोग करते हैं।

1 <summary>{attrs.name}</summary>
2 <pre>
3 {JSON.stringify(attrs.object, null, 2)}

अधिकांश फ़ील्ड JSON.stringify (opens in a new tab) का उपयोग करके प्रदर्शित किए जाते हैं।

1 </pre>
2 { funs.length > 0 &&
3 <>
4 फ़ंक्शन:
5 <ul>

अपवाद फ़ंक्शन हैं, जो JSON मानक (opens in a new tab) का हिस्सा नहीं हैं, इसलिए उन्हें अलग से प्रदर्शित करना होगा।

1 {funs.map((f, i) =>

JSX के भीतर, { घुंघराले कोष्ठक } के अंदर के कोड को जावास्क्रिप्ट के रूप में व्याख्या किया जाता है। फिर, ( नियमित कोष्ठक ) के अंदर के कोड की फिर से JSX के रूप में व्याख्या की जाती है।

1 (<li key={i}>{f}</li>)
2 )}

रिएक्ट को DOM ट्री (opens in a new tab) में टैग के लिए अलग पहचानकर्ता की आवश्यकता होती है। इसका मतलब है कि एक ही टैग के बच्चों (इस मामले में, अनऑर्डर्ड सूची (opens in a new tab)), को अलग-अलग key विशेषताओं की आवश्यकता होती है।

1 </ul>
2 </>
3 }
4 </details>
5 </>
6}

विभिन्न HTML टैग समाप्त करें।

अंतिम export
1export { Greeter }

Greeter घटक वह है जिसे हमें एप्लिकेशन के लिए निर्यात करने की आवश्यकता है।

src/wagmi.ts

अंत में, WAGMI से संबंधित विभिन्न परिभाषाएँ src/wagmi.ts में हैं। मैं यहां सब कुछ समझाने नहीं जा रहा हूं, क्योंकि इसका अधिकांश हिस्सा बॉयलरप्लेट है जिसे आपको बदलने की संभावना नहीं है।

यहां का कोड github पर (opens in a new tab) जैसा बिल्कुल नहीं है क्योंकि बाद में लेख में हम एक और चेन (Redstone होलस्की (opens in a new tab)) जोड़ते हैं।

1import { getDefaultWallets } from '@rainbow-me/rainbowkit'
2import { configureChains, createConfig } from 'wagmi'
3import { holesky, sepolia } from 'wagmi/chains'

एप्लिकेशन द्वारा समर्थित ब्लॉकचेन आयात करें। आप समर्थित चेनों की सूची viem github में (opens in a new tab) देख सकते हैं।

1import { publicProvider } from 'wagmi/providers/public'
2
3const walletConnectProjectId = 'c96e690bb92b6311e8e9b2a6a22df575'

वॉलेटकनेक्ट (opens in a new tab) का उपयोग करने में सक्षम होने के लिए आपको अपने एप्लिकेशन के लिए एक प्रोजेक्ट ID की आवश्यकता है। आप इसे cloud.walletconnect.com पर (opens in a new tab) प्राप्त कर सकते हैं।

1const { chains, publicClient, webSocketPublicClient } = configureChains(
2 [ holesky, sepolia ],
3 [
4 publicProvider(),
5 ],
6)
7
8const { connectors } = getDefaultWallets({
9 appName: 'My wagmi + RainbowKit App',
10 chains,
11 projectId: walletConnectProjectId,
12})
13
14export const config = createConfig({
15 autoConnect: true,
16 connectors,
17 publicClient,
18 webSocketPublicClient,
19})
20
21export { chains }

एक और ब्लॉकचेन जोड़ना

इन दिनों बहुत सारे L2 स्केलिंग समाधान हैं, और आप कुछ ऐसे का समर्थन करना चाह सकते हैं जिन्हें viem अभी तक समर्थन नहीं करता है। ऐसा करने के लिए, आप src/wagmi.ts को संशोधित करते हैं। ये निर्देश बताते हैं कि Redstone होलस्की (opens in a new tab) कैसे जोड़ा जाए।

  1. viem से defineChain प्रकार आयात करें।

    1import { defineChain } from 'viem'
  2. नेटवर्क परिभाषा जोड़ें।

    1const redstoneHolesky = defineChain({
    2 id: 17_001,
    3 name: 'Redstone होलस्की',
    4 network: 'redstone-holesky',
    5 nativeCurrency: {
    6 decimals: 18,
    7 name: 'Ether',
    8 symbol: 'ETH',
    9 },
    10 rpcUrls: {
    11 default: {
    12 http: ['https://rpc.holesky.redstone.xyz'],
    13 webSocket: ['wss://rpc.holesky.redstone.xyz/ws'],
    14 },
    15 public: {
    16 http: ['https://rpc.holesky.redstone.xyz'],
    17 webSocket: ['wss://rpc.holesky.redstone.xyz/ws'],
    18 },
    19 },
    20 blockExplorers: {
    21 default: { name: 'Explorer', url: 'https://explorer.holesky.redstone.xyz' },
    22 },
    23})
  3. नई चेन को configureChains कॉल में जोड़ें।

    1 const { chains, publicClient, webSocketPublicClient } = configureChains(
    2 [ holesky, sepolia, redstoneHolesky ],
    3 [ publicProvider(), ],
    4 )
  4. सुनिश्चित करें कि एप्लिकेशन नए नेटवर्क पर आपके अनुबंधों के लिए पता जानता है। इस मामले में, हम src/components/Greeter.tsx को संशोधित करते हैं:

    1const contractAddrs : AddressPerBlockchainType = {
    2 // होलस्की
    3 17000: '0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8',
    4
    5 // Redstone होलस्की
    6 17001: '0x4919517f82a1B89a32392E1BF72ec827ba9986D3',
    7
    8 // सेपोलिया
    9 11155111: '0x7143d5c190F048C8d19fe325b748b081903E3BF0'
    10}

निष्कर्ष

बेशक, आप वास्तव में Greeter के लिए एक यूज़र इंटरफ़ेस प्रदान करने की परवाह नहीं करते हैं। आप अपने स्वयं के अनुबंधों के लिए एक यूज़र इंटरफ़ेस बनाना चाहते हैं। अपना स्वयं का एप्लिकेशन बनाने के लिए, इन चरणों को चलाएँ:

  1. एक wagmi एप्लिकेशन बनाने के लिए निर्दिष्ट करें।

    1pnpm create wagmi
  2. एप्लिकेशन को नाम दें।

  3. रिएक्ट फ्रेमवर्क चुनें।

  4. वीट वैरिएंट चुनें।

  5. आप Rainbow kit (opens in a new tab) जोड़ सकते हैं।

अब जाएँ और अपने अनुबंधों को व्यापक दुनिया के लिए प्रयोग करने योग्य बनाएँ।

मेरे और काम के लिए यहाँ देखें (opens in a new tab)

पेज का अंतिम अपडेट: 3 मार्च 2026

क्या यह ट्यूटोरियल सहायक था?