Kujenga kiolesura cha mtumiaji kwa ajili ya mkataba wako
Umepata kipengele tunachohitaji katika mfumo wa ikolojia wa Ethereum. Umeandika mikataba mahiri ili kukitekeleza, na labda hata baadhi ya kodi zinazohusiana zinazoendeshwa nje ya mnyororo. Hili ni jambo zuri! Kwa bahati mbaya, bila kiolesura cha mtumiaji hutakuwa na watumiaji wowote, na mara ya mwisho ulipoandika tovuti watu walitumia modemu za kupiga simu na JavaScript ilikuwa mpya.
Makala haya ni kwa ajili yako. Ninachukulia kuwa unajua upangaji programu, na labda kidogo JavaScript na HTML, lakini ujuzi wako wa kiolesura cha mtumiaji umepitwa na wakati. Pamoja tutapitia programu rahisi ya kisasa ili uone jinsi inavyofanywa siku hizi.
Kwa nini hii ni muhimu
Kinadharia, unaweza tu kuwafanya watu watumie Etherscan (opens in a new tab) au Blockscout (opens in a new tab) ili kuingiliana na mikataba yako. Hiyo ni nzuri kwa Waethereans wenye uzoefu. Lakini tunajaribu kuhudumia watu wengine bilioni moja (opens in a new tab). Hili halitafanyika bila uzoefu mzuri wa mtumiaji, na kiolesura rafiki cha mtumiaji ni sehemu kubwa ya hilo.
Programu ya Greeter
Kuna nadharia nyingi nyuma ya jinsi UI ya kisasa inavyofanya kazi, na tovuti nyingi nzuri (opens in a new tab) zinazoelezea hilo (opens in a new tab). Badala ya kurudia kazi nzuri iliyofanywa na tovuti hizo, nitachukulia kuwa unapendelea kujifunza kwa kufanya na kuanza na programu unayoweza kucheza nayo. Bado unahitaji nadharia ili kufanya mambo, na tutaifikia - tutaenda tu faili la chanzo kwa faili la chanzo, na kujadili mambo tunapoyafikia.
Usakinishaji
-
Programu inatumia mtandao wa majaribio wa Sepolia (opens in a new tab). Ikiwa ni lazima, pata ETH ya majaribio ya Sepolia na uongeze Sepolia kwenye mkoba wako (opens in a new tab).
-
Nakili hazina ya GitHub na usakinishe vifurushi vinavyohitajika.
git clone https://github.com/qbzzt/260301-modern-ui-web3.git cd 260301-modern-ui-web3 npm install -
Programu inatumia vituo vya ufikiaji vya bure, ambavyo vina mapungufu ya utendaji. Ikiwa unataka kutumia mtoa huduma wa Nodi kama huduma, badilisha URL katika
src/wagmi.ts. -
Anzisha programu.
npm run dev -
Vinjari kwenye URL inayoonyeshwa na programu. Katika hali nyingi, hiyo ni http://localhost:5173/ (opens in a new tab).
-
Unaweza kuona kodi ya chanzo ya mkataba, toleo lililobadilishwa la Greeter ya Hardhat, kwenye kichunguzi cha mnyororo wa vitalu (opens in a new tab).
Kupitia faili
index.html
Faili hili ni kiolezo cha kawaida cha HTML isipokuwa kwa mstari huu, ambao unaingiza faili la hati.
<script type="module" src="/src/main.tsx"></script>
src/main.tsx
Kiendelezi cha faili kinaonyesha kuwa hiki ni kijenzi cha React (opens in a new tab) kilichoandikwa katika TypeScript (opens in a new tab), kiendelezi cha JavaScript kinachounga mkono ukaguzi wa aina (opens in a new tab). TypeScript inakusanywa kuwa JavaScript, kwa hivyo tunaweza kuitumia upande wa mteja.
Faili hili linaelezwa zaidi ikiwa una nia. Kawaida hubadilishi faili hili, bali src/App.tsx na faili inazoingiza.
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import React from 'react'
import ReactDOM from 'react-dom/client'
import { WagmiProvider } from 'wagmi'
Ingiza kodi ya maktaba tunayohitaji.
import App from './App.tsx'
Ingiza kijenzi cha React kinachotekeleza programu (tazama hapa chini).
import { config } from './wagmi.ts'
Ingiza usanidi wa wagmi (opens in a new tab), ambao unajumuisha usanidi wa mnyororo wa vitalu.
const queryClient = new QueryClient()
Inaunda mfano mpya wa meneja wa kache wa React Query (opens in a new tab). Kitu hiki kitahifadhi:
- Wito wa RPC uliowekwa kwenye kache
- Usomaji wa mkataba
- Hali ya kuchukua tena chinichini
Tunahitaji meneja wa kache kwa sababu wagmi v3 inatumia React Query kwa ndani.
ReactDOM.createRoot(document.getElementById('root')!).render(
Unda kijenzi cha msingi cha React. Kigezo cha render ni JSX (opens in a new tab), lugha ya kiendelezi inayotumia HTML na JavaScript/TypeScript. Alama ya mshangao hapa inaiambia kijenzi cha TypeScript: "hujui kwamba document.getElementById('root') itakuwa kigezo halali kwa ReactDOM.createRoot, lakini usijali - mimi ni msanidi programu na ninakuambia kutakuwa na".
<React.StrictMode>
Programu inaingia ndani ya kijenzi cha React.StrictMode (opens in a new tab). Kijenzi hiki kinaiambia maktaba ya React kuingiza ukaguzi wa ziada wa utatuzi, ambao ni muhimu wakati wa usanidi.
<WagmiProvider config={config}>
Programu pia iko ndani ya kijenzi cha WagmiProvider (opens in a new tab). Maktaba ya wagmi (tutaifanya) (opens in a new tab) inaunganisha ufafanuzi wa UI wa React na maktaba ya viem (opens in a new tab) kwa ajili ya kuandika programu tumizi iliyogatuliwa (dapp) ya Ethereum.
<QueryClientProvider client={queryClient}>
Na hatimaye, ongeza mtoa huduma wa React Query ili kijenzi chochote cha programu kiweze kutumia hoja zilizowekwa kwenye kache.
<App />
Sasa tunaweza kuwa na kijenzi cha programu, ambacho kwa kweli kinatekeleza UI. /> mwishoni mwa kijenzi inaiambia React kwamba kijenzi hiki hakina ufafanuzi wowote ndani yake, kulingana na kiwango cha XML.
</QueryClientProvider>
</WagmiProvider>
</React.StrictMode>,
)
Bila shaka, tunapaswa kufunga vijenzi vingine.
src/App.tsx
import {
useConnect,
useConnection,
useDisconnect,
useSwitchChain
} from 'wagmi'
import { useEffect } from 'react'
import { Greeter } from './Greeter'
Ingiza maktaba tunazohitaji, pamoja na kijenzi cha Greeter.
const SEPOLIA_CHAIN_ID = 11155111
Kitambulisho cha mnyororo wa Sepolia.
function App() {
Hii ndiyo njia ya kawaida ya kuunda kijenzi cha React: fafanua chaguo la kukokotoa ambalo linaitwa wakati wowote linapohitaji kutolewa. Chaguo hili la kukokotoa kwa kawaida lina kodi ya TypeScript au JavaScript, ikifuatiwa na taarifa ya return inayorudisha kodi ya JSX.
const connection = useConnection()
Tumia useConnection (opens in a new tab) kupata taarifa zinazohusiana na muunganisho wa sasa, kama vile anwani na chainId.
Kwa kawaida, katika React chaguo za kukokotoa zinazoitwa use... ni ndoano (hooks) (opens in a new tab). Chaguo hizi za kukokotoa hazirudishi tu data kwenye kijenzi; pia zinahakikisha inatolewa tena (chaguo la kukokotoa la kijenzi linatekelezwa tena, na pato lake linachukua nafasi ya lile la awali katika HTML) wakati data hiyo inabadilika.
const { connectors, connect, status, error } = useConnect()
Tumia useConnect (opens in a new tab) kupata taarifa kuhusu muunganisho wa mkoba.
const { disconnect } = useDisconnect()
Ndoano hii (opens in a new tab) inatupa chaguo la kukokotoa la kukata muunganisho kutoka kwenye mkoba.
const { switchChain } = useSwitchChain()
Ndoano hii (opens in a new tab) inaturuhusu kubadili minyororo.
useEffect(() => {
Ndoano ya React useEffect (opens in a new tab) inakuruhusu kuendesha chaguo la kukokotoa wakati wowote thamani ya kigezo inabadilika ili kusawazisha mfumo wa nje.
if (connection.status === 'connected' &&
connection.chainId !== SEPOLIA_CHAIN_ID
) {
switchChain({ chainId: SEPOLIA_CHAIN_ID })
}
Ikiwa tumeunganishwa, lakini si kwenye mnyororo wa vitalu wa Sepolia, badili kwenda Sepolia.
}, [connection.status, connection.chainId])
Endesha tena chaguo la kukokotoa kila wakati hali ya muunganisho au chainId ya muunganisho inabadilika.
return (
<>
JSX ya kijenzi cha React lazima irudishe kijenzi kimoja cha HTML. Tunapokuwa na vijenzi vingi na hatuhitaji kontena la kuvifunga vyote, tunatumia kijenzi kitupu (<> ... </>) kuviunganisha kuwa kijenzi kimoja.
<h2>Connection</h2>
<div>
status: {connection.status}
<br />
addresses: {JSON.stringify(connection.addresses)}
<br />
chainId: {connection.chainId}
</div>
Toa taarifa kuhusu muunganisho wa sasa. Ndani ya JSX, {<expression>} inamaanisha kutathmini usemi kama JavaScript.
{connection.status === 'connected' && (
Sintaksia {<condition> && <value>} means "if the condition is true, evaluate to the value; if it isn't, evaluate to false`".
Hii ndiyo njia ya kawaida ya kuweka taarifa za if ndani ya JSX.
<div>
<Greeter />
<hr />
JSX inafuata kiwango cha XML, ambacho ni kikali zaidi kuliko HTML. Ikiwa lebo haina lebo ya mwisho inayolingana, lazima iwe na mkwaju (/) mwishoni ili kuikomesha.
Hapa tuna lebo mbili kama hizo, <Greeter /> (ambayo kwa kweli ina kodi ya HTML inayozungumza na mkataba) na <hr /> kwa ajili ya mstari wa mlalo (opens in a new tab).
<button type="button" onClick={disconnect}>
Disconnect
</button>
</div>
)}
Ikiwa mtumiaji atabofya kitufe hiki, ita chaguo la kukokotoa la disconnect.
{connection.status !== 'connected' && (
Ikiwa hatujaunganishwa, onyesha chaguo zinazohitajika ili kuunganisha kwenye mkoba.
<div>
<h2>Connect</h2>
{connectors.map((connector) => (
Katika connectors tuna orodha ya viunganishi. Tunatumia map (opens in a new tab) kuigeuza kuwa orodha ya vitufe vya JSX vya kuonyesha.
<button
key={connector.uid}
Katika JSX ni lazima kwa lebo "ndugu" (lebo zinazotoka kwa mzazi mmoja) kuwa na vitambulisho tofauti.
onClick={() => connect({ connector })}
type="button"
>
{connector.name}
</button>
))}
Vitufe vya kiunganishi.
<div>{status}</div>
<div>{error?.message}</div>
</div>
)}
Toa taarifa za ziada. Sintaksia ya usemi <variable>?.<field> inaiambia JavaScript kwamba ikiwa kigezo kimefafanuliwa, tathmini kwenye uwanja huo. Ikiwa kigezo hakijafafanuliwa, basi usemi huu unatathminiwa kuwa undefined.
Usemi error.message, wakati hakuna hitilafu, ungeibua ubaguzi. Kutumia error?.message kunaturuhusu kuepuka suala hilo.
src/Greeter.tsx
Faili hili lina utendaji mwingi wa UI. Linajumuisha ufafanuzi ambao kwa kawaida ungekuwa katika faili nyingi, lakini kwa kuwa huu ni mafunzo, programu imeboreshwa ili iwe rahisi kueleweka mara ya kwanza, badala ya utendaji au urahisi wa matengenezo.
import {
useState,
useEffect,
} from 'react'
import { useChainId,
useAccount,
useReadContract,
useWriteContract,
useWatchContractEvent,
useSimulateContract
} from 'wagmi'
Tunatumia chaguo hizi za kukokotoa za maktaba. Tena, zinaelezwa hapa chini zinapotumika.
import { AddressType } from 'abitype'
Maktaba ya abitype (opens in a new tab) inatupa ufafanuzi wa TypeScript kwa aina mbalimbali za data za Ethereum, kama vile AddressType (opens in a new tab).
let greeterABI = [
{ "type": "function", "name": "greet", ... },
{ "type": "function", "name": "setGreeting", ... },
{ "type": "event", "name": "SetGreeting", ... },
] as const // greeterABI
ABI kwa ajili ya mkataba wa Greeter.
Ikiwa unaunda mikataba na UI kwa wakati mmoja, kwa kawaida ungeziweka katika hazina moja na kutumia ABI inayozalishwa na kikusanyaji cha Solidity kama faili katika programu yako. Hata hivyo, hii si lazima hapa kwa sababu mkataba tayari umeundwa na hautabadilika.
Tunatumia as const (opens in a new tab) kuiambia TypeScript kwamba hii ni konstanti halisi. Kwa kawaida, unapobainisha katika JavaScript const x = {"a": 1}, unaweza kubadilisha thamani katika x, huwezi tu kuikabidhi.
type AddressPerBlockchainType = {
[key: number]: AddressType
}
TypeScript ina aina kali. Tunatumia ufafanuzi huu kubainisha anwani ambapo mkataba wa Greeter umesambazwa kwenye minyororo tofauti. Ufunguo ni nambari (chainId), na thamani ni AddressType (anwani).
const contractAddrs : AddressPerBlockchainType = {
// Sepolia
11155111: '0xC87506C66c7896366b9E988FE0aA5B6dDE77CFfA'
}
Anwani ya mkataba kwenye Sepolia (opens in a new tab).
Kijenzi cha Timer
Kijenzi cha Timer kinaonyesha idadi ya sekunde tangu wakati fulani. Hii ni muhimu kwa madhumuni ya utumiaji. Watumiaji wanapofanya jambo, wanatarajia majibu ya haraka. Katika minyororo ya vitalu, hii mara nyingi haiwezekani kwa sababu hakuna kinachotokea hadi muamala uwekwe kwenye kitalu. Suluhisho moja ni kuonyesha muda ambao umepita tangu mtumiaji afanye kitendo, ili mtumiaji aweze kuamua ikiwa muda unaohitajika ni wa kuridhisha.
type TimerProps = {
lastUpdate: Date
}
Kijenzi cha Timer kinachukua kigezo kimoja, lastUpdate, ambacho ni wakati wa kitendo cha mwisho.
const Timer = ({ lastUpdate }: TimerProps) => {
const [_, setNow] = useState(new Date())
Tunahitaji kuwa na hali (kigezo kilichofungwa kwenye kijenzi) na kuisasisha ili kijenzi kifanye kazi kwa usahihi. Lakini hatuhitaji kamwe kuisoma, kwa hivyo usijisumbue kufanya kigezo.
useEffect(() => {
const id = setInterval(() => setNow(new Date()), 1000)
return () => clearInterval(id)
}, [])
Chaguo la kukokotoa la setInterval (opens in a new tab) linaturuhusu kupanga chaguo la kukokotoa kuendeshwa mara kwa mara. Katika kesi hii, kila sekunde. Chaguo la kukokotoa linaita setNow ili kusasisha hali, kwa hivyo kijenzi cha Timer kitatolewa tena. Tunafunga hii ndani ya useEffect (opens in a new tab) na orodha tupu ya utegemezi ili itokee mara moja tu, badala ya kila wakati kijenzi kinapotolewa.
const secondsSinceUpdate = Math.floor(
(Date.now() - lastUpdate.getTime()) / 1000
)
return (
<span>{secondsSinceUpdate} seconds ago</span>
)
}
Kokotoa idadi ya sekunde tangu sasisho la mwisho na uirudishe.
Kijenzi cha Greeter
const Greeter = () => {
Hatimaye, tunapata kufafanua kijenzi.
const chainId = useChainId()
const account = useAccount()
Taarifa kuhusu mnyororo na akaunti tunayotumia, kwa hisani ya wagmi (opens in a new tab). Kwa sababu hii ni ndoano (use...), kijenzi kinatolewa tena wakati wowote taarifa hii inabadilika.
const greeterAddr = chainId && contractAddrs[chainId]
Anwani ya mkataba wa Greeter, ambayo ni undefined ikiwa hatuna taarifa za mnyororo, au tuko kwenye mnyororo usio na mkataba huo.
const readResults = useReadContract({
address: greeterAddr,
abi: greeterABI,
functionName: "greet", // Hakuna hoja
})
Ndoano ya useReadContract (opens in a new tab) inaita chaguo la kukokotoa la greet la mkataba (opens in a new tab).
const [ currentGreeting, setCurrentGreeting ] =
useState("Please wait while we fetch the greeting from the blockchain...")
const [ newGreeting, setNewGreeting ] = useState("")
Ndoano ya React ya useState (opens in a new tab) inaturuhusu kubainisha kigezo cha hali, ambacho thamani yake inadumu kutoka utoaji mmoja wa kijenzi hadi mwingine. Thamani ya awali ni kigezo, katika kesi hii mfuatano mtupu.
Ndoano ya useState inarudisha orodha yenye thamani mbili:
- Thamani ya sasa ya kigezo cha hali.
- Chaguo la kukokotoa la kurekebisha kigezo cha hali inapohitajika. Kwa kuwa hii ni ndoano, kila wakati inapoitwa kijenzi kinatolewa tena.
Katika kesi hii, tunatumia kigezo cha hali kwa ajili ya salamu mpya ambayo mtumiaji anataka kuweka.
const [ lastSetterAddress, setLastSetterAddress ] = useState("")
Ikiwa watumiaji wengi wanatumia mkataba mmoja kwa wakati mmoja, wanaweza kufuta salamu za kila mmoja. Hii ingeonekana kwa watumiaji kana kwamba programu haifanyi kazi vizuri. Ikiwa programu inaonyesha ni nani aliyeweka salamu mwisho, mtumiaji atajua alikuwa mtu mwingine na kwamba programu inafanya kazi kwa usahihi.
const [ status, setStatus ] = useState("")
const [ statusTime, setStatusTime ] = useState(new Date())
Watumiaji wanapenda kuona kwamba vitendo vyao vina athari ya haraka. Hata hivyo, kwenye mnyororo wa vitalu, hii sivyo. Vigezo hivi vya hali vinaturuhusu angalau kuonyesha kitu kwa watumiaji ili wajue kitendo chao kinaendelea.
useEffect(() => {
if (readResults.data) {
setCurrentGreeting(readResults.data)
setStatus("Greeting fetched from blockchain")
}
}, [readResults.data])
Ikiwa readResults hapo juu inabadilisha data na haijawekwa kwa thamani ya uongo (kwa mfano, undefined), sasisha salamu ya sasa kwa ile iliyosomwa kutoka kwenye mnyororo wa vitalu. Pia, sasisha hali.
useWatchContractEvent({
address: greeterAddr,
abi: greeterABI,
eventName: 'SetGreeting',
chainId,
Sikiliza matukio ya SetGreeting.
enabled: !!greeterAddr,
!!<value> inamaanisha kwamba ikiwa thamani ni false, au thamani inayotathminiwa kama uongo, kama vile undefined, 0, au mfuatano mtupu, usemi kwa ujumla ni false. Kwa thamani nyingine yoyote, ni true. Ni njia ya kubadilisha thamani kuwa boolean, kwa sababu ikiwa hakuna greeterAddr, hatutaki kusikiliza matukio.
onLogs: logs => {
const greetingFromContract = logs[0].args.greeting
setCurrentGreeting(greetingFromContract)
setLastSetterAddress(logs[0].args.sender)
updateStatus("Greeting updated by event")
},
})
Tunapoona kumbukumbu (ambayo hutokea tunapoona tukio jipya), inamaanisha kwamba salamu imebadilishwa. Katika kesi hiyo, tunaweza kusasisha currentGreeting na lastSetterAddress kwa thamani mpya. Pia, tunataka kusasisha onyesho la hali.
const updateStatus = (newStatus: string) => {
setStatus(newStatus)
setStatusTime(new Date())
}
Tunaposasisha hali tunataka kufanya mambo mawili:
- Sasisha mfuatano wa hali (
status) - Sasisha wakati wa sasisho la mwisho la hali (
statusTime) kuwa sasa.
const greetingChange = (evt) =>
setNewGreeting(evt.target.value)
Hiki ni kidhibiti cha tukio kwa mabadiliko kwenye uwanja mpya wa kuingiza salamu. Tungeweza kubainisha aina ya kigezo cha evt, lakini TypeScript ni lugha ya hiari ya aina. Kwa kuwa chaguo hili la kukokotoa linaitwa mara moja tu, katika kidhibiti cha tukio cha HTML, sidhani kama ni lazima.
const { writeContractAsync } = useWriteContract()
Chaguo la kukokotoa la kuandika kwenye mkataba. Inafanana na writeContracts (opens in a new tab), lakini inawezesha masasisho bora ya hali.
const simulation = useSimulateContract({
address: greeterAddr,
abi: greeterABI,
functionName: 'setGreeting',
args: [newGreeting],
account: account.address
})
Huu ndio mchakato wa kuwasilisha muamala wa mnyororo wa vitalu kutoka kwa mtazamo wa mteja:
- Tuma muamala kwenye nodi katika mnyororo wa vitalu ukitumia
eth_estimateGas(opens in a new tab). - Subiri majibu kutoka kwenye nodi.
- Majibu yanapopokelewa, muombe mtumiaji atie saini muamala kupitia mkoba. Hatua hii lazima ifanyike baada ya majibu ya nodi kupokelewa kwa sababu mtumiaji anaonyeshwa gharama ya gesi ya muamala kabla ya kuutia saini.
- Subiri mtumiaji aidhinishe.
- Tuma muamala tena, wakati huu ukitumia
eth_sendRawTransaction(opens in a new tab).
Hatua ya 2 ina uwezekano wa kuchukua muda unaoonekana, ambapo watumiaji wanaweza kujiuliza ikiwa amri yao ilipokelewa na kiolesura cha mtumiaji na kwa nini hawajaombwa kutia saini muamala bado. Hiyo inaunda uzoefu mbaya wa mtumiaji (UX).
Suluhisho moja ni kutuma eth_estimateGas kila wakati kigezo kinapobadilika. Kisha, wakati mtumiaji anataka kutuma muamala (katika kesi hii kwa kubonyeza Sasisha salamu), gharama ya gesi inajulikana, na mtumiaji anaweza kuona ukurasa wa mkoba mara moja.
return (
Sasa hatimaye tunaweza kuunda HTML halisi ya kurudisha.
<>
<h2>Greeter</h2>
{currentGreeting}
Onyesha salamu ya sasa.
{lastSetterAddress && (
<p>Last updated by {
lastSetterAddress === account.address ? "you" : lastSetterAddress
}</p>
)}
Ikiwa tunajua ni nani aliyeweka salamu mwisho, onyesha taarifa hiyo. Greeter haifuatilii taarifa hii, na hatutaki kuangalia nyuma kwa matukio ya SetGreeting, kwa hivyo tunaipata tu mara tu salamu inapobadilishwa wakati tunaendesha.
<hr />
<input type="text"
value={newGreeting}
onChange={greetingChange}
/>
<br />
Huu ni uwanja wa maandishi wa kuingiza ambapo mtumiaji anaweza kuweka salamu mpya. Kila wakati mtumiaji anapobonyeza kitufe, tunaita greetingChange, ambayo inaita setNewGreeting. Kwa kuwa setNewGreeting inatoka kwa useState, inasababisha kijenzi cha Greeter kutolewa tena. Hii inamaanisha kwamba:
- Tunahitaji kubainisha
valueili kuweka thamani ya salamu mpya, kwa sababu vinginevyo ingerudi kwenye chaguo-msingi, mfuatano mtupu. simulationpia inasasishwa kila wakatinewGreetinginabadilika, ambayo inamaanisha kwamba tutapata uigaji na salamu sahihi. Hii inaweza kuwa muhimu kwa sababu gharama ya gesi inategemea ukubwa wa data ya wito, ambayo inategemea urefu wa mfuatano.
<button disabled={!simulation.data}
Wezesha kitufe tu mara tu tunapokuwa na taarifa tunayohitaji kutuma muamala.
onClick={async () => {
updateStatus("Please confirm in wallet...")
Sasisha hali. Katika hatua hii, mtumiaji anahitaji kuthibitisha kwenye mkoba.
await writeContractAsync(simulation.data.request)
updateStatus("Transaction sent, waiting for greeting to change...")
}}
>
Update greeting
</button>
writeContractAsync inarudi tu baada ya muamala kutumwa kwa kweli. Hii inaturuhusu kumuonyesha mtumiaji muda ambao muamala umekuwa ukisubiri kujumuishwa kwenye mnyororo wa vitalu.
<h4>Status: {status}</h4>
<p>Updated <Timer lastUpdate={statusTime} /> </p>
</>
)
}
Onyesha hali na muda ambao umepita tangu isasishwe.
export {Greeter}
Hamisha kijenzi.
src/wagmi.ts
Hatimaye, ufafanuzi mbalimbali unaohusiana na wagmi uko katika src/wagmi.ts. Sitaelezea kila kitu hapa, kwa sababu mengi yake ni kiolezo ambacho huenda hutahitaji kubadilisha.
import { http, webSocket, createConfig, fallback } from 'wagmi'
import { sepolia } from 'wagmi/chains'
import { injected } from 'wagmi/connectors'
export const config = createConfig({
chains: [sepolia],
Usanidi wa wagmi unajumuisha minyororo inayoungwa mkono na programu hii. Unaweza kuona orodha ya minyororo inayopatikana (opens in a new tab).
connectors: [
injected(),
],
Kiunganishi hiki (opens in a new tab) kinaturuhusu kuzungumza na mkoba uliosakinishwa kwenye kivinjari.
transports: {
[sepolia.id]: http()
Mwisho wa HTTP wa chaguo-msingi unaokuja na Viem ni mzuri vya kutosha. Ikiwa tunataka URL tofauti, tunaweza kutumia http("https:// hostname ") au webSocket("wss:// hostname ").
},
multiInjectedProviderDiscovery: false,
})
Kuongeza mnyororo mwingine wa vitalu
Siku hizi kuna suluhu nyingi za kuongeza ukubwa za L2 (opens in a new tab), na unaweza kutaka kuunga mkono baadhi ambazo viem haiungi mkono bado. Ili kufanya hivyo, unarekebisha src/wagmi.ts. Maagizo haya yanaelezea jinsi ya kuongeza Optimism Sepolia (opens in a new tab).
-
Hariri
src/wagmi.tsA. Ingiza aina ya
defineChainkutoka viem.import { defineChain } from 'viem'B. Ongeza ufafanuzi wa mtandao. Huhitaji kufanya hivi kwa Optimism Sepolia, tayari iko katika
viem(opens in a new tab), lakini kwa njia hii unajifunza jinsi ya kuongeza mnyororo wa vitalu ambao hauko katikaviem.const optimismSepolia = defineChain({ id: 11_155_420, name: 'OP Sepolia', nativeCurrency: { name: 'Sepolia Ether', symbol: 'ETH', decimals: 18 }, rpcUrls: { default: { http: ['https://sepolia.optimism.io'], webSocket: ['wss://optimism-sepolia.drpc.org'], }, }, blockExplorers: { default: { name: 'Blockscout', url: 'https://optimism-sepolia.blockscout.com', apiUrl: 'https://optimism-sepolia.blockscout.com/api', } }, })C. Ongeza mnyororo mpya kwenye wito wa
createConfig.export const config = createConfig({ chains: [sepolia, optimismSepolia], connectors: [ injected(), ], transports: { [optimismSepolia.id]: http(), [sepolia.id]: http() }, multiInjectedProviderDiscovery: false, }) -
Hariri
src/App.tsxili kutoa maoni kuhusu ubadilishaji wa kiotomatiki kwenda Sepolia. Kwenye mfumo wa uzalishaji, labda ungeonyesha vitufe vilivyo na viungo kwa kila mnyororo wa vitalu unaounga mkono./* useEffect(() => { if (connection.status === 'connected' && connection.chainId !== SEPOLIA_CHAIN_ID ) { switchChain({ chainId: SEPOLIA_CHAIN_ID }) } }, [connection.status, connection.chainId]) */ -
Hariri
src/Greeter.tsxili kuhakikisha kwamba programu inajua anwani ya mikataba yako kwenye mtandao mpya.const contractAddrs: AddressPerBlockchainType = { // Optimism Sepolia 11155420: "0x4dd85791923E9294E934271522f63875EAe5806f", // Sepolia 11155111: "0x7143d5c190F048C8d19fe325b748b081903E3BF0", } -
Kwenye kivinjari chako.
A. Vinjari kwenye ChainList (opens in a new tab) na ubofye mojawapo ya vitufe upande wa kulia wa jedwali ili kuongeza mnyororo kwenye mkoba wako.
B. Katika programu, Kata muunganisho na kisha uunganishe tena ili kubadilisha mnyororo wa vitalu. Kuna njia nzuri zaidi za kushughulikia hili, lakini zingehitaji mabadiliko ya programu.
Hitimisho
Bila shaka, hujali sana kuhusu kutoa kiolesura cha mtumiaji kwa ajili ya Greeter. Unataka kuunda kiolesura cha mtumiaji kwa ajili ya mikataba yako mwenyewe. Ili kuunda programu yako mwenyewe, endesha hatua hizi:
-
Bainisha kuunda programu ya wagmi.
npm create wagmi -
Andika
yili kuendelea. -
Taja programu.
-
Chagua mfumo wa React.
-
Chagua lahaja ya Vite.
Sasa nenda na ufanye mikataba yako itumike kwa ulimwengu mpana.