Kontrak Pintar Hello World untuk Pemula - Fullstack
Panduan ini ditujukan untuk Anda jika Anda baru dalam pengembangan blockchain dan tidak tahu harus mulai dari mana atau bagaimana cara menerapkan dan berinteraksi dengan kontrak pintar. Kita akan membahas pembuatan dan penerapan kontrak pintar sederhana di testnet Goerli menggunakan MetaMask (opens in a new tab), Solidity (opens in a new tab), Hardhat (opens in a new tab), dan Alchemy (opens in a new tab).
Anda akan membutuhkan akun Alchemy untuk menyelesaikan tutorial ini. Daftar untuk mendapatkan akun gratis (opens in a new tab).
Jika Anda memiliki pertanyaan kapan saja, jangan ragu untuk menghubungi kami di Discord Alchemy (opens in a new tab)!
Bagian 1 - Membuat dan Menerapkan Kontrak Pintar Anda menggunakan Hardhat
Terhubung ke jaringan Ethereum
Ada banyak cara untuk membuat permintaan ke rantai Ethereum. Untuk mempermudah, kita akan menggunakan akun gratis di Alchemy, sebuah platform pengembang blockchain dan API yang memungkinkan kita untuk berkomunikasi dengan rantai Ethereum tanpa menjalankan node sendiri. Alchemy juga memiliki alat pengembang untuk pemantauan dan analitik; kita akan memanfaatkan ini dalam tutorial ini untuk memahami apa yang terjadi di balik layar dalam penerapan kontrak pintar kita.
Buat aplikasi dan kunci API Anda
Setelah Anda membuat akun Alchemy, Anda dapat menghasilkan kunci API dengan membuat aplikasi. Ini akan memungkinkan Anda untuk membuat permintaan ke testnet Goerli. Jika Anda tidak terbiasa dengan testnet, Anda dapat membaca panduan Alchemy untuk memilih jaringan (opens in a new tab).
Di dasbor Alchemy, temukan menu tarik-turun Apps di bilah navigasi dan klik Create App.
Beri nama aplikasi Anda 'Hello World' dan tulis deskripsi singkat. Pilih Staging sebagai lingkungan Anda dan Goerli sebagai jaringan Anda.
Catatan: pastikan untuk memilih Goerli, atau tutorial ini tidak akan berfungsi.
Klik Create app. Aplikasi Anda akan muncul di tabel di bawah ini.
Buat akun Ethereum
Anda memerlukan akun Ethereum untuk mengirim dan menerima transaksi. Kita akan menggunakan MetaMask, dompet virtual di peramban yang memungkinkan pengguna mengelola alamat akun Ethereum mereka.
Anda dapat mengunduh dan membuat akun MetaMask secara gratis di sini (opens in a new tab). Saat Anda membuat akun, atau jika Anda sudah memiliki akun, pastikan untuk beralih ke "Goerli Test Network" di kanan atas (sehingga kita tidak berurusan dengan uang sungguhan).
Langkah 4: Tambahkan ether dari Faucet
Untuk menerapkan kontrak pintar Anda ke jaringan pengujian (testnet), Anda akan memerlukan beberapa ETH palsu. Untuk mendapatkan ETH di jaringan Goerli, buka faucet Goerli dan masukkan alamat akun Goerli Anda. Perhatikan bahwa faucet Goerli akhir-akhir ini bisa sedikit tidak dapat diandalkan - lihat halaman jaringan pengujian untuk daftar opsi yang dapat dicoba:
Catatan: karena kepadatan jaringan, ini mungkin memakan waktu beberapa saat. ``
Langkah 5: Periksa Saldo Anda
Untuk memeriksa kembali apakah ETH ada di dompet Anda, mari buat permintaan eth_getBalance (opens in a new tab) menggunakan alat komposer Alchemy (opens in a new tab). Ini akan mengembalikan jumlah ETH di dompet kita. Untuk mempelajari lebih lanjut, lihat tutorial singkat Alchemy tentang cara menggunakan alat komposer (opens in a new tab).
Masukkan alamat akun MetaMask Anda dan klik Send Request. Anda akan melihat respons yang terlihat seperti cuplikan kode di bawah ini.
1{ "jsonrpc": "2.0", "id": 0, "result": "0x2B5E3AF16B1880000" }Catatan: Hasil ini dalam wei, bukan ETH. Wei digunakan sebagai denominasi terkecil dari ether.
Fiuh! Uang palsu kita semuanya ada di sana.
Langkah 6: Inisialisasi proyek kita
Pertama, kita perlu membuat folder untuk proyek kita. Navigasikan ke baris perintah Anda dan masukkan yang berikut ini.
1mkdir hello-world2cd hello-worldSekarang kita berada di dalam folder proyek kita, kita akan menggunakan npm init untuk menginisialisasi proyek.
Jika Anda belum menginstal npm, ikuti instruksi ini untuk menginstal Node.js dan npm (opens in a new tab).
Untuk tujuan tutorial ini, tidak masalah bagaimana Anda menjawab pertanyaan inisialisasi. Berikut adalah cara kami melakukannya sebagai referensi:
1package name: (hello-world)2version: (1.0.0)3description: hello world smart contract4entry point: (index.js)5test command:6git repository:7keywords:8author:9license: (ISC)1011About to write to /Users/.../.../.../hello-world/package.json:1213{14 "name": "hello-world",15 "version": "1.0.0",16 "description": "hello world smart contract",17 "main": "index.js",18 "scripts": {19 "test": "echo \"Error: no test specified\" && exit 1"20 },21 "author": "",22 "license": "ISC"23}Tampilkan semuaSetujui package.json dan kita siap untuk melanjutkan!
Langkah 7: Unduh Hardhat
Hardhat adalah lingkungan pengembangan untuk mengompilasi, menerapkan, menguji, dan men-debug perangkat lunak Ethereum Anda. Ini membantu pengembang saat membangun kontrak pintar dan dapps secara lokal sebelum menerapkannya ke rantai langsung.
Di dalam proyek hello-world kita, jalankan:
1npm install --save-dev hardhatLihat halaman ini untuk detail lebih lanjut tentang instruksi instalasi (opens in a new tab).
Langkah 8: Buat proyek Hardhat
Di dalam folder proyek hello-world kita, jalankan:
1npx hardhatAnda kemudian akan melihat pesan selamat datang dan opsi untuk memilih apa yang ingin Anda lakukan. Pilih "create an empty hardhat.config.js":
1888 888 888 888 8882888 888 888 888 8883888 888 888 888 88848888888888 8888b. 888d888 .d88888 88888b. 8888b. 8888885888 888 "88b 888P" d88" 888 888 "88b "88b 8886888 888 .d888888 888 888 888 888 888 .d888888 8887888 888 888 888 888 Y88b 888 888 888 888 888 Y88b.8888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888910👷 Welcome to Hardhat v2.0.11 👷1112What do you want to do? …13Create a sample project14❯ Create an empty hardhat.config.js15QuitTampilkan semuaIni akan menghasilkan file hardhat.config.js di dalam proyek. Kita akan menggunakan ini nanti dalam tutorial untuk menentukan pengaturan proyek kita.
Langkah 9: Tambahkan folder proyek
Untuk menjaga proyek tetap teratur, mari buat dua folder baru. Di baris perintah, navigasikan ke direktori root proyek hello-world Anda dan ketik:
1mkdir contracts2mkdir scriptscontracts/adalah tempat kita akan menyimpan file kode kontrak pintar hello world kitascripts/adalah tempat kita akan menyimpan skrip untuk menerapkan dan berinteraksi dengan kontrak kita
Langkah 10: Tulis kontrak kita
Anda mungkin bertanya pada diri sendiri, kapan kita akan menulis kode? Sekarang saatnya!
Buka proyek hello-world di editor favorit Anda. Kontrak pintar paling sering ditulis dalam Solidity, yang akan kita gunakan untuk menulis kontrak pintar kita.
- Navigasikan ke folder
contractsdan buat file baru bernamaHelloWorld.sol - Di bawah ini adalah contoh kontrak pintar Hello World yang akan kita gunakan untuk tutorial ini. Salin konten di bawah ini ke dalam file
HelloWorld.sol.
Catatan: Pastikan untuk membaca komentar untuk memahami apa yang dilakukan kontrak ini.
1// Specifies the version of Solidity, using semantic versioning.2// Learn more: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma3pragma solidity >=0.7.3;45// Defines a contract named `HelloWorld`.6// A contract is a collection of functions and data (its state). Once deployed, a contract resides at a specific address on the Ethereum blockchain. Learn more: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html7contract HelloWorld {89 //Emitted when update function is called10 //Smart contract events are a way for your contract to communicate that something happened on the blockchain to your app front-end, which can be 'listening' for certain events and take action when they happen.11 event UpdatedMessages(string oldStr, string newStr);1213 // Declares a state variable `message` of type `string`.14 // State variables are variables whose values are permanently stored in contract storage. The keyword `public` makes variables accessible from outside a contract and creates a function that other contracts or clients can call to access the value.15 string public message;1617 // Similar to many class-based object-oriented languages, a constructor is a special function that is only executed upon contract creation.18 // Constructors are used to initialize the contract's data. Learn more:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors19 constructor(string memory initMessage) {2021 // Accepts a string argument `initMessage` and sets the value into the contract's `message` storage variable).22 message = initMessage;23 }2425 // A public function that accepts a string argument and updates the `message` storage variable.26 function update(string memory newMessage) public {27 string memory oldMsg = message;28 message = newMessage;29 emit UpdatedMessages(oldMsg, newMessage);30 }31}Tampilkan semuaIni adalah kontrak pintar dasar yang menyimpan pesan saat pembuatan. Ini dapat diperbarui dengan memanggil fungsi update.
Langkah 11: Hubungkan MetaMask & Alchemy ke proyek Anda
Kita telah membuat dompet MetaMask, akun Alchemy, dan menulis kontrak pintar kita, sekarang saatnya untuk menghubungkan ketiganya.
Setiap transaksi yang dikirim dari dompet Anda memerlukan tanda tangan digital menggunakan kunci pribadi unik Anda. Untuk memberikan izin ini kepada program kita, kita dapat menyimpan kunci pribadi kita dengan aman di file lingkungan (environment file). Kita juga akan menyimpan kunci API untuk Alchemy di sini.
Untuk mempelajari lebih lanjut tentang mengirim transaksi, lihat tutorial ini (opens in a new tab) tentang mengirim transaksi menggunakan web3.
Pertama, instal paket dotenv di direktori proyek Anda:
1npm install dotenv --saveKemudian, buat file .env di direktori root proyek. Tambahkan kunci pribadi MetaMask Anda dan URL API HTTP Alchemy ke dalamnya.
File lingkungan Anda harus diberi nama .env atau tidak akan dikenali sebagai file lingkungan.
Jangan menamainya process.env atau .env-custom atau apa pun yang lain.
- Ikuti instruksi ini (opens in a new tab) untuk mengekspor kunci pribadi Anda
- Lihat di bawah untuk mendapatkan URL API HTTP Alchemy
File .env Anda akan terlihat seperti ini:
1API_URL = "https://eth-goerli.alchemyapi.io/v2/your-api-key"2PRIVATE_KEY = "your-metamask-private-key"Untuk benar-benar menghubungkan ini ke kode kita, kita akan mereferensikan variabel-variabel ini di file hardhat.config.js kita pada langkah 13.
Langkah 12: Instal Ethers.js
Ethers.js adalah pustaka yang memudahkan untuk berinteraksi dan membuat permintaan ke Ethereum dengan membungkus metode JSON-RPC standar (opens in a new tab) dengan metode yang lebih ramah pengguna.
Hardhat memungkinkan kita untuk mengintegrasikan plugin (opens in a new tab) untuk perkakas tambahan dan fungsionalitas yang diperluas. Kita akan memanfaatkan plugin Ethers (opens in a new tab) untuk penerapan kontrak.
Di direktori proyek Anda, ketik:
npm install --save-dev @nomiclabs/hardhat-ethers "ethers@^5.0.0"Langkah 13: Perbarui hardhat.config.js
Kita telah menambahkan beberapa dependensi dan plugin sejauh ini, sekarang kita perlu memperbarui hardhat.config.js sehingga proyek kita mengetahui semuanya.
Perbarui hardhat.config.js Anda agar terlihat seperti ini:
1/**2 * @type import('hardhat/config').HardhatUserConfig3 */45require("dotenv").config()6require("@nomiclabs/hardhat-ethers")78const { API_URL, PRIVATE_KEY } = process.env910module.exports = {11 solidity: "0.7.3",12 defaultNetwork: "goerli",13 networks: {14 hardhat: {},15 goerli: {16 url: API_URL,17 accounts: [`0x${PRIVATE_KEY}`],18 },19 },20}Tampilkan semuaLangkah 14: Kompilasi kontrak kita
Untuk memastikan semuanya berfungsi sejauh ini, mari kompilasi kontrak kita. Tugas compile adalah salah satu tugas bawaan Hardhat.
Dari baris perintah, jalankan:
npx hardhat compileAnda mungkin mendapatkan peringatan tentang SPDX license identifier not provided in source file, tetapi tidak perlu khawatir tentang itu — semoga semuanya terlihat bagus! Jika tidak, Anda selalu dapat mengirim pesan di Discord Alchemy (opens in a new tab).
Langkah 15: Tulis skrip penerapan kita
Sekarang setelah kontrak kita ditulis dan file konfigurasi kita siap, saatnya untuk menulis skrip penerapan kontrak kita.
Navigasikan ke folder scripts/ dan buat file baru bernama deploy.js , lalu tambahkan konten berikut ke dalamnya:
1async function main() {2 const HelloWorld = await ethers.getContractFactory("HelloWorld")34 // Start deployment, returning a promise that resolves to a contract object // Mulai penyebaran, mengembalikan promise yang menghasilkan objek kontrak5 const hello_world = await HelloWorld.deploy("Hello World!")6 console.log("Contract deployed to address:", hello_world.address)7}89main()10 .then(() => process.exit(0))11 .catch((error) => {12 console.error(error)13 process.exit(1)14 })Tampilkan semuaHardhat melakukan pekerjaan yang luar biasa dalam menjelaskan apa yang dilakukan setiap baris kode ini dalam tutorial Kontrak (opens in a new tab) mereka, kami telah mengadopsi penjelasan mereka di sini.
1const HelloWorld = await ethers.getContractFactory("HelloWorld")Sebuah ContractFactory di ethers.js adalah abstraksi yang digunakan untuk menerapkan kontrak pintar baru, jadi HelloWorld di sini adalah pabrik (factory) (opens in a new tab) untuk instansiasi kontrak hello world kita. Saat menggunakan plugin hardhat-ethers, instansiasi ContractFactory dan Contract terhubung ke penandatangan pertama (pemilik) secara default.
1const hello_world = await HelloWorld.deploy()Memanggil deploy() pada ContractFactory akan memulai penerapan, dan mengembalikan Promise yang diselesaikan menjadi objek Contract. Ini adalah objek yang memiliki metode untuk setiap fungsi kontrak pintar kita.
Langkah 16: Terapkan kontrak kita
Kita akhirnya siap untuk menerapkan kontrak pintar kita! Navigasikan ke baris perintah dan jalankan:
npx hardhat run scripts/deploy.js --network goerliAnda kemudian akan melihat sesuatu seperti:
Contract deployed to address: 0x6cd7d44516a20882cEa2DE9f205bF401c0d23570Harap simpan alamat ini. Kita akan menggunakannya nanti dalam tutorial.
Jika kita pergi ke Goerli etherscan (opens in a new tab) dan mencari alamat kontrak kita, kita seharusnya dapat melihat bahwa itu telah berhasil diterapkan. Transaksi akan terlihat seperti ini:
Alamat From harus cocok dengan alamat akun MetaMask Anda dan alamat To akan mengatakan Contract Creation. Jika kita mengklik transaksi, kita akan melihat alamat kontrak kita di bidang To.
Selamat! Anda baru saja menerapkan kontrak pintar ke testnet Ethereum.
Untuk memahami apa yang terjadi di balik layar, mari navigasikan ke tab Explorer di dasbor Alchemy (opens in a new tab) kita. Jika Anda memiliki beberapa aplikasi Alchemy, pastikan untuk memfilter berdasarkan aplikasi dan pilih Hello World.
Di sini Anda akan melihat beberapa metode JSON-RPC yang dibuat Hardhat/Ethers di balik layar untuk kita saat kita memanggil fungsi .deploy(). Dua metode penting di sini adalah eth_sendRawTransaction (opens in a new tab), yang merupakan permintaan untuk menulis kontrak kita ke rantai Goerli, dan eth_getTransactionByHash (opens in a new tab), yang merupakan permintaan untuk membaca informasi tentang transaksi kita berdasarkan hash. Untuk mempelajari lebih lanjut tentang mengirim transaksi, lihat tutorial kami tentang mengirim transaksi menggunakan Web3.
Bagian 2: Berinteraksi dengan Kontrak Pintar Anda
Sekarang setelah kita berhasil menerapkan kontrak pintar ke jaringan Goerli, mari kita pelajari cara berinteraksi dengannya.
Buat file interact.js
Ini adalah file tempat kita akan menulis skrip interaksi kita. Kita akan menggunakan pustaka Ethers.js yang sebelumnya Anda instal di Bagian 1.
Di dalam folder scripts/, buat file baru bernama interact.js dan tambahkan kode berikut:
1// interact.js // interact.js23const API_KEY = process.env.API_KEY4const PRIVATE_KEY = process.env.PRIVATE_KEY5const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESSPerbarui file .env Anda
Kita akan menggunakan variabel lingkungan baru, jadi kita perlu mendefinisikannya di file .env yang kita buat sebelumnya.
Kita perlu menambahkan definisi untuk API_KEY Alchemy kita dan CONTRACT_ADDRESS tempat kontrak pintar Anda diterapkan.
File .env Anda akan terlihat seperti ini:
# .env # .envAPI_URL = "https://eth-goerli.alchemyapi.io/v2/<your-api-key>"API_KEY = "<your-api-key>"PRIVATE_KEY = "<your-metamask-private-key>"CONTRACT_ADDRESS = "0x<your contract address>"Ambil ABI kontrak Anda
kontrak kita adalah antarmuka untuk berinteraksi dengan kontrak pintar kita. Hardhat secara otomatis menghasilkan ABI dan menyimpannya di HelloWorld.json. Untuk menggunakan ABI, kita perlu mengurai isinya dengan menambahkan baris kode berikut ke file interact.js kita:
1// interact.js // interact.js2const contract = require("../artifacts/contracts/HelloWorld.sol/HelloWorld.json")Jika Anda ingin melihat ABI, Anda dapat mencetaknya ke konsol Anda:
1console.log(JSON.stringify(contract.abi))Untuk melihat ABI Anda dicetak ke konsol, navigasikan ke terminal Anda dan jalankan:
npx hardhat run scripts/interact.jsBuat instansiasi kontrak Anda
Untuk berinteraksi dengan kontrak kita, kita perlu membuat instansiasi kontrak dalam kode kita. Untuk melakukannya dengan Ethers.js, kita perlu bekerja dengan tiga konsep:
- Provider - penyedia node yang memberi Anda akses baca dan tulis ke blockchain
- Signer - mewakili akun Ethereum yang dapat menandatangani transaksi
- Contract - objek Ethers.js yang mewakili kontrak tertentu yang diterapkan onchain
Kita akan menggunakan ABI kontrak dari langkah sebelumnya untuk membuat instansiasi kontrak kita:
1// interact.js // interact.js23// Provider // Provider4const alchemyProvider = new ethers.providers.AlchemyProvider(5 (network = "goerli"),6 API_KEY7)89// Signer // Signer10const signer = new ethers.Wallet(PRIVATE_KEY, alchemyProvider)1112// Contract // Kontrak13const helloWorldContract = new ethers.Contract(14 CONTRACT_ADDRESS,15 contract.abi,16 signer17)Tampilkan semuaPelajari lebih lanjut tentang Provider, Signer, dan Contract di dokumentasi ethers.js (opens in a new tab).
Baca pesan inisialisasi
Ingat ketika kita menerapkan kontrak kita dengan initMessage = "Hello world!"? Kita sekarang akan membaca pesan yang disimpan dalam kontrak pintar kita dan mencetaknya ke konsol.
Dalam JavaScript, fungsi asinkron digunakan saat berinteraksi dengan jaringan. Untuk mempelajari lebih lanjut tentang fungsi asinkron, baca artikel medium ini (opens in a new tab).
Gunakan kode di bawah ini untuk memanggil fungsi message dalam kontrak pintar kita dan membaca pesan inisialisasi:
1// interact.js // interact.js23// ... // ...45async function main() {6 const message = await helloWorldContract.message()7 console.log("The message is: " + message)8}9main()Tampilkan semuaSetelah menjalankan file menggunakan npx hardhat run scripts/interact.js di terminal, kita akan melihat respons ini:
1The message is: Hello world!Selamat! Anda baru saja berhasil membaca data kontrak pintar dari blockchain Ethereum, kerja bagus!
Perbarui pesan
Alih-alih hanya membaca pesan, kita juga dapat memperbarui pesan yang disimpan dalam kontrak pintar kita menggunakan fungsi update! Keren, kan?
Untuk memperbarui pesan, kita dapat langsung memanggil fungsi update pada objek Contract yang telah kita instansiasi:
1// interact.js // interact.js23// ... // ...45async function main() {6 const message = await helloWorldContract.message()7 console.log("The message is: " + message)89 console.log("Updating the message...")10 const tx = await helloWorldContract.update("This is the new message.")11 await tx.wait()12}13main()Tampilkan semuaPerhatikan bahwa pada baris 11, kita memanggil .wait() pada objek transaksi yang dikembalikan. Ini memastikan bahwa skrip kita menunggu transaksi ditambang di blockchain sebelum keluar dari fungsi. Jika panggilan .wait() tidak disertakan, skrip mungkin tidak melihat nilai message yang diperbarui dalam kontrak.
Baca pesan baru
Anda seharusnya dapat mengulangi langkah sebelumnya untuk membaca nilai message yang diperbarui. Luangkan waktu sejenak dan lihat apakah Anda dapat membuat perubahan yang diperlukan untuk mencetak nilai baru tersebut!
Jika Anda butuh petunjuk, inilah tampilan file interact.js Anda pada tahap ini:
1// interact.js // interact.js23const API_KEY = process.env.API_KEY4const PRIVATE_KEY = process.env.PRIVATE_KEY5const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS67const contract = require("../artifacts/contracts/HelloWorld.sol/HelloWorld.json")89// provider - Alchemy // provider - Alchemy10const alchemyProvider = new ethers.providers.AlchemyProvider(11 (network = "goerli"),12 API_KEY13)1415// signer - you // signer - Anda16const signer = new ethers.Wallet(PRIVATE_KEY, alchemyProvider)1718// contract instance // instans kontrak19const helloWorldContract = new ethers.Contract(20 CONTRACT_ADDRESS,21 contract.abi,22 signer23)2425async function main() {26 const message = await helloWorldContract.message()27 console.log("The message is: " + message)2829 console.log("Updating the message...")30 const tx = await helloWorldContract.update("this is the new message")31 await tx.wait()3233 const newMessage = await helloWorldContract.message()34 console.log("The new message is: " + newMessage)35}3637main()Tampilkan semuaSekarang jalankan saja skripnya dan Anda seharusnya dapat melihat pesan lama, status pembaruan, dan pesan baru dicetak ke terminal Anda!
npx hardhat run scripts/interact.js --network goerli
1The message is: Hello World!2Updating the message...3The new message is: This is the new message.Saat menjalankan skrip tersebut, Anda mungkin memperhatikan bahwa langkah Updating the message... membutuhkan waktu beberapa saat untuk dimuat sebelum pesan baru dimuat. Hal itu disebabkan oleh proses penambangan; jika Anda penasaran untuk melacak transaksi saat sedang ditambang, kunjungi mempool Alchemy (opens in a new tab) untuk melihat status transaksi. Jika transaksi dibatalkan, ada baiknya juga untuk memeriksa Goerli Etherscan (opens in a new tab) dan mencari hash transaksi Anda.
Bagian 3: Publikasikan Kontrak Pintar Anda ke Etherscan
Anda telah melakukan semua kerja keras untuk menghidupkan kontrak pintar Anda; sekarang saatnya untuk membagikannya kepada dunia!
Dengan memverifikasi kontrak pintar Anda di Etherscan, siapa pun dapat melihat kode sumber Anda dan berinteraksi dengan kontrak pintar Anda. Mari kita mulai!
Langkah 1: Buat Kunci API di akun Etherscan Anda
Kunci API Etherscan diperlukan untuk memverifikasi bahwa Anda memiliki kontrak pintar yang Anda coba publikasikan.
Jika Anda belum memiliki akun Etherscan, daftar untuk membuat akun (opens in a new tab).
Setelah masuk, temukan nama pengguna Anda di bilah navigasi, arahkan kursor ke atasnya dan pilih tombol My profile.
Di halaman profil Anda, Anda akan melihat bilah navigasi samping. Dari bilah navigasi samping, pilih API Keys. Selanjutnya, tekan tombol "Add" untuk membuat kunci API baru, beri nama aplikasi Anda hello-world dan tekan tombol Create New API Key.
Kunci API baru Anda akan muncul di tabel kunci API. Salin kunci API ke papan klip Anda.
Selanjutnya, kita perlu menambahkan kunci API Etherscan ke file .env kita.
Setelah menambahkannya, file .env Anda akan terlihat seperti ini:
1API_URL = "https://eth-goerli.alchemyapi.io/v2/your-api-key"2PUBLIC_KEY = "your-public-account-address"3PRIVATE_KEY = "your-private-account-address"4CONTRACT_ADDRESS = "your-contract-address"5ETHERSCAN_API_KEY = "your-etherscan-key"Kontrak pintar yang disebarkan dengan Hardhat
Instal hardhat-etherscan
Mempublikasikan kontrak Anda ke Etherscan menggunakan Hardhat sangatlah mudah. Anda pertama-tama perlu menginstal plugin hardhat-etherscan untuk memulai. hardhat-etherscan akan secara otomatis memverifikasi kode sumber dan ABI kontrak pintar di Etherscan. Untuk menambahkannya, di direktori hello-world jalankan:
1npm install --save-dev @nomiclabs/hardhat-etherscanSetelah diinstal, sertakan pernyataan berikut di bagian atas hardhat.config.js Anda, dan tambahkan opsi konfigurasi Etherscan:
1// hardhat.config.js // hardhat.config.js23require("dotenv").config()4require("@nomiclabs/hardhat-ethers")5require("@nomiclabs/hardhat-etherscan")67const { API_URL, PRIVATE_KEY, ETHERSCAN_API_KEY } = process.env89module.exports = {10 solidity: "0.7.3",11 defaultNetwork: "goerli",12 networks: {13 hardhat: {},14 goerli: {15 url: API_URL,16 accounts: [`0x${PRIVATE_KEY}`],17 },18 },19 etherscan: {20 // Your API key for Etherscan // Kunci API Anda untuk Etherscan21 // Obtain one at https://etherscan.io/ // Dapatkan di https://etherscan.io/22 apiKey: ETHERSCAN_API_KEY,23 },24}Tampilkan semuaVerifikasi kontrak pintar Anda di Etherscan
Pastikan semua file disimpan dan semua variabel .env dikonfigurasi dengan benar.
Jalankan tugas verify, dengan meneruskan alamat kontrak, dan jaringan tempat kontrak tersebut disebarkan:
1npx hardhat verify --network goerli DEPLOYED_CONTRACT_ADDRESS 'Hello World!'Pastikan bahwa DEPLOYED_CONTRACT_ADDRESS adalah alamat kontrak pintar Anda yang disebarkan di jaringan pengujian Goerli. Selain itu, argumen terakhir ('Hello World!') harus berupa nilai string yang sama yang digunakan selama langkah penyebaran di bagian 1.
Jika semuanya berjalan lancar, Anda akan melihat pesan berikut di terminal Anda:
1Successfully submitted source code for contract2contracts/HelloWorld.sol:HelloWorld at 0xdeployed-contract-address3for verification on Etherscan. Waiting for verification result...456Successfully verified contract HelloWorld on Etherscan.7https://goerli.etherscan.io/address/<contract-address>#contracts // goerli.etherscan.io/address/<contract-address>#contractsSelamat! Kode kontrak pintar Anda ada di Etherscan!
Lihat kontrak pintar Anda di Etherscan!
Saat Anda menavigasi ke tautan yang disediakan di terminal Anda, Anda seharusnya dapat melihat kode kontrak pintar dan ABI Anda dipublikasikan di Etherscan!
Wahooo - Anda berhasil, juara! Sekarang siapa pun dapat memanggil atau menulis ke kontrak pintar Anda! Kami tidak sabar untuk melihat apa yang Anda bangun selanjutnya!
Bagian 4 - Mengintegrasikan kontrak pintar Anda dengan frontend
Pada akhir tutorial ini, Anda akan mengetahui cara:
- Menghubungkan dompet MetaMask ke dapp Anda
- Membaca data dari kontrak pintar Anda menggunakan API Alchemy Web3 (opens in a new tab)
- Menandatangani transaksi Ethereum menggunakan MetaMask
Untuk dapp ini, kita akan menggunakan React (opens in a new tab) sebagai kerangka kerja frontend kita; namun, penting untuk dicatat bahwa kita tidak akan menghabiskan banyak waktu untuk menguraikan dasar-dasarnya, karena kita sebagian besar akan berfokus pada membawa fungsionalitas Web3 ke proyek kita.
Sebagai prasyarat, Anda harus memiliki pemahaman tingkat pemula tentang React. Jika tidak, kami menyarankan untuk menyelesaikan tutorial Pengantar React (opens in a new tab) resmi.
Kloning file pemula
Pertama, buka repositori GitHub hello-world-part-four (opens in a new tab) untuk mendapatkan file pemula untuk proyek ini dan kloning repositori ini ke mesin lokal Anda.
Buka repositori yang dikloning secara lokal. Perhatikan bahwa repositori ini berisi dua folder: starter-files dan completed.
starter-files- kita akan bekerja di direktori ini, kita akan menghubungkan UI ke dompet Ethereum Anda dan kontrak pintar yang kita publikasikan ke Etherscan di Bagian 3.completedberisi seluruh tutorial yang telah selesai dan hanya boleh digunakan sebagai referensi jika Anda mengalami kebuntuan.
Selanjutnya, buka salinan starter-files Anda di editor kode favorit Anda, lalu navigasikan ke dalam folder src.
Semua kode yang akan kita tulis akan berada di bawah folder src. Kita akan mengedit komponen HelloWorld.js dan file JavaScript util/interact.js untuk memberikan fungsionalitas Web3 pada proyek kita.
Periksa file pemula
Sebelum kita mulai membuat kode, mari kita jelajahi apa yang disediakan untuk kita di file pemula.
Jalankan proyek react Anda
Mari kita mulai dengan menjalankan proyek React di peramban kita. Keindahan React adalah setelah kita menjalankan proyek di peramban, setiap perubahan yang kita simpan akan diperbarui secara langsung di peramban kita.
Untuk menjalankan proyek, navigasikan ke direktori root dari folder starter-files, dan jalankan npm install di terminal Anda untuk menginstal dependensi proyek:
cd starter-filesnpm installSetelah selesai menginstal, jalankan npm start di terminal Anda:
npm startMelakukan hal tersebut akan membuka http://localhost:3000/ (opens in a new tab) di peramban Anda, di mana Anda akan melihat frontend untuk proyek kita. Ini harus terdiri dari satu bidang (tempat untuk memperbarui pesan yang disimpan di kontrak pintar Anda), tombol "Connect Wallet", dan tombol "Update".
Jika Anda mencoba mengklik salah satu tombol, Anda akan menyadari bahwa tombol tersebut tidak berfungsi—itu karena kita masih perlu memprogram fungsionalitasnya.
Komponen HelloWorld.js
Mari kembali ke folder src di editor kita dan buka file HelloWorld.js. Sangat penting bagi kita untuk memahami semua yang ada di file ini, karena ini adalah komponen React utama yang akan kita kerjakan.
Di bagian atas file ini, Anda akan melihat bahwa kita memiliki beberapa pernyataan impor yang diperlukan untuk menjalankan proyek kita, termasuk pustaka React, hook useEffect dan useState, beberapa item dari ./util/interact.js (kita akan menjelaskannya lebih detail segera!), dan logo Alchemy.
1// HelloWorld.js // HelloWorld.js23import React from "react"4import { useEffect, useState } from "react"5import {6 helloWorldContract,7 connectWallet,8 updateMessage,9 loadCurrentMessage,10 getCurrentWalletConnected,11} from "./util/interact.js"1213import alchemylogo from "./alchemylogo.svg"Tampilkan semuaSelanjutnya, kita memiliki variabel status yang akan kita perbarui setelah peristiwa tertentu.
1// HelloWorld.js // HelloWorld.js23//State variables // Variabel state4const [walletAddress, setWallet] = useState("")5const [status, setStatus] = useState("")6const [message, setMessage] = useState("No connection to the network.")7const [newMessage, setNewMessage] = useState("")Berikut adalah apa yang diwakili oleh masing-masing variabel:
walletAddress- string yang menyimpan alamat dompet penggunastatus- string yang menyimpan pesan bermanfaat yang memandu pengguna tentang cara berinteraksi dengan dappmessage- string yang menyimpan pesan saat ini di kontrak pintarnewMessage- string yang menyimpan pesan baru yang akan ditulis ke kontrak pintar
Setelah variabel status, Anda akan melihat lima fungsi yang belum diimplementasikan: useEffect ,addSmartContractListener, addWalletListener , connectWalletPressed, dan onUpdatePressed. Kita akan menjelaskan apa yang mereka lakukan di bawah ini:
1// HelloWorld.js // HelloWorld.js23//called only once // hanya dipanggil sekali4useEffect(async () => {5 //TODO: implement // TODO: implementasikan6}, [])78function addSmartContractListener() {9 //TODO: implement // TODO: implementasikan10}1112function addWalletListener() {13 //TODO: implement // TODO: implementasikan14}1516const connectWalletPressed = async () => {17 //TODO: implement // TODO: implementasikan18}1920const onUpdatePressed = async () => {21 //TODO: implement // TODO: implementasikan22}Tampilkan semuauseEffect(opens in a new tab)- ini adalah hook React yang dipanggil setelah komponen Anda dirender. Karena ia memiliki prop array kosong[]yang diteruskan ke dalamnya (lihat baris 4), ia hanya akan dipanggil pada render pertama komponen. Di sini kita akan memuat pesan saat ini yang disimpan di kontrak pintar kita, memanggil pendengar kontrak pintar dan dompet kita, dan memperbarui UI kita untuk mencerminkan apakah dompet sudah terhubung.addSmartContractListener- fungsi ini menyiapkan pendengar yang akan mengawasi peristiwaUpdatedMessagesdari kontrak HelloWorld kita dan memperbarui UI kita ketika pesan diubah di kontrak pintar kita.addWalletListener- fungsi ini menyiapkan pendengar yang mendeteksi perubahan pada status dompet MetaMask pengguna, seperti ketika pengguna memutuskan sambungan dompet mereka atau beralih alamat.connectWalletPressed- fungsi ini akan dipanggil untuk menghubungkan dompet MetaMask pengguna ke dapp kita.onUpdatePressed- fungsi ini akan dipanggil ketika pengguna ingin memperbarui pesan yang disimpan di kontrak pintar.
Di dekat akhir file ini, kita memiliki UI dari komponen kita.
1// HelloWorld.js // HelloWorld.js23//the UI of our component // UI dari komponen kita4return (5 <div id="container">6 <img id="logo" src={alchemylogo}></img>7 <button id="walletButton" onClick={connectWalletPressed}>8 {walletAddress.length > 0 ? (9 "Connected: " +10 String(walletAddress).substring(0, 6) +11 "..." +12 String(walletAddress).substring(38)13 ) : (14 <span>Connect Wallet</span>15 )}16 </button>1718 <h2 style={{ paddingTop: "50px" }}>Current Message:</h2>19 <p>{message}</p>2021 <h2 style={{ paddingTop: "18px" }}>New Message:</h2>2223 <div>24 <input25 type="text"26 placeholder="Update the message in your smart contract."27 onChange={(e) => setNewMessage(e.target.value)}28 value={newMessage}29 />30 <p id="status">{status}</p>3132 <button id="publishButton" onClick={onUpdatePressed}>33 Update34 </button>35</div>36 37</div>38)Tampilkan semuaJika Anda memindai kode ini dengan cermat, Anda akan melihat di mana kita menggunakan berbagai variabel status kita di UI kita:
- Pada baris 6-12, jika dompet pengguna terhubung (yaitu,
walletAddress.length > 0), kita menampilkan versi terpotong dariwalletAddresspengguna di tombol dengan ID "walletButton;" jika tidak, ia hanya mengatakan "Connect Wallet." - Pada baris 17, kita menampilkan pesan saat ini yang disimpan di kontrak pintar, yang ditangkap dalam string
message. - Pada baris 23-26, kita menggunakan komponen terkontrol (opens in a new tab) untuk memperbarui variabel status
newMessagekita ketika input di bidang teks berubah.
Selain variabel status kita, Anda juga akan melihat bahwa fungsi connectWalletPressed dan onUpdatePressed dipanggil ketika tombol dengan ID publishButton dan walletButton masing-masing diklik.
Terakhir, mari kita bahas di mana komponen HelloWorld.js ini ditambahkan.
Jika Anda pergi ke file App.js, yang merupakan komponen utama di React yang bertindak sebagai wadah untuk semua komponen lainnya, Anda akan melihat bahwa komponen HelloWorld.js kita disuntikkan pada baris 7.
Terakhir namun tidak kalah pentingnya, mari kita periksa satu file lagi yang disediakan untuk Anda, file interact.js.
File interact.js
Karena kita ingin mengikuti paradigma M-V-C (opens in a new tab), kita akan menginginkan file terpisah yang berisi semua fungsi kita untuk mengelola logika, data, dan aturan dapp kita, dan kemudian dapat mengekspor fungsi-fungsi tersebut ke frontend kita (komponen HelloWorld.js kita).
👆🏽Inilah tujuan pasti dari file interact.js kita!
Navigasikan ke folder util di direktori src Anda, dan Anda akan melihat bahwa kita telah menyertakan file bernama interact.js yang akan berisi semua interaksi kontrak pintar dan fungsi serta variabel dompet kita.
1// interact.js // interact.js23//export const helloWorldContract; // export const helloWorldContract;45export const loadCurrentMessage = async () => {}67export const connectWallet = async () => {}89const getCurrentWalletConnected = async () => {}1011export const updateMessage = async (message) => {}Tampilkan semuaAnda akan melihat di bagian atas file bahwa kita telah mengomentari objek helloWorldContract. Nanti dalam tutorial ini, kita akan menghapus komentar objek ini dan membuat instansiasi kontrak pintar kita di variabel ini, yang kemudian akan kita ekspor ke komponen HelloWorld.js kita.
Empat fungsi yang belum diimplementasikan setelah objek helloWorldContract kita melakukan hal berikut:
loadCurrentMessage- fungsi ini menangani logika memuat pesan saat ini yang disimpan di kontrak pintar. Ini akan melakukan panggilan baca ke kontrak pintar Hello World menggunakan API Alchemy Web3 (opens in a new tab).connectWallet- fungsi ini akan menghubungkan MetaMask pengguna ke dapp kita.getCurrentWalletConnected- fungsi ini akan memeriksa apakah akun Ethereum sudah terhubung ke dapp kita saat halaman dimuat dan memperbarui UI kita sesuai dengan itu.updateMessage- fungsi ini akan memperbarui pesan yang disimpan di kontrak pintar. Ini akan melakukan panggilan tulis ke kontrak pintar Hello World, sehingga dompet MetaMask pengguna harus menandatangani transaksi Ethereum untuk memperbarui pesan.
Sekarang setelah kita memahami apa yang sedang kita kerjakan, mari kita cari tahu cara membaca dari kontrak pintar kita!
Langkah 3: Membaca dari kontrak pintar Anda
Untuk membaca dari kontrak pintar Anda, Anda harus berhasil menyiapkan:
- Koneksi API ke rantai Ethereum
- Instansiasi yang dimuat dari kontrak pintar Anda
- Fungsi untuk memanggil fungsi kontrak pintar Anda
- Pendengar untuk mengawasi pembaruan ketika data yang Anda baca dari kontrak pintar berubah
Ini mungkin terdengar seperti banyak langkah, tetapi jangan khawatir! Kami akan memandu Anda tentang cara melakukan masing-masing langkah demi langkah! :)
Buat koneksi API ke rantai Ethereum
Jadi ingat bagaimana di Bagian 2 dari tutorial ini, kita menggunakan kunci Alchemy Web3 kita untuk membaca dari kontrak pintar kita (opens in a new tab)? Anda juga akan memerlukan kunci Alchemy Web3 di dapp Anda untuk membaca dari rantai.
Jika Anda belum memilikinya, pertama-tama instal Alchemy Web3 (opens in a new tab) dengan menavigasi ke direktori root dari starter-files Anda dan menjalankan yang berikut ini di terminal Anda:
1npm install @alch/alchemy-web3Alchemy Web3 (opens in a new tab) adalah pembungkus di sekitar Web3.js (opens in a new tab), menyediakan metode API yang ditingkatkan dan manfaat penting lainnya untuk membuat hidup Anda sebagai pengembang web3 lebih mudah. Ini dirancang untuk memerlukan konfigurasi minimal sehingga Anda dapat mulai menggunakannya di aplikasi Anda segera!
Kemudian, instal paket dotenv (opens in a new tab) di direktori proyek Anda, sehingga kita memiliki tempat yang aman untuk menyimpan kunci API kita setelah kita mengambilnya.
1npm install dotenv --saveUntuk dapp kita, kita akan menggunakan kunci API Websockets kita alih-alih kunci API HTTP kita, karena ini akan memungkinkan kita untuk menyiapkan pendengar yang mendeteksi ketika pesan yang disimpan di kontrak pintar berubah.
Setelah Anda memiliki kunci API Anda, buat file .env di direktori root Anda dan tambahkan url Alchemy Websockets Anda ke dalamnya. Setelah itu, file .env Anda akan terlihat seperti ini:
1REACT_APP_ALCHEMY_KEY = wss://eth-goerli.ws.alchemyapi.io/v2/<key> // eth-goerli.ws.alchemyapi.io/v2/<key>Sekarang, kita siap untuk menyiapkan titik akhir Alchemy Web3 kita di dapp kita! Mari kembali ke interact.js kita, yang bersarang di dalam folder util kita dan tambahkan kode berikut di bagian atas file:
1// interact.js // interact.js23require("dotenv").config()4const alchemyKey = process.env.REACT_APP_ALCHEMY_KEY5const { createAlchemyWeb3 } = require("@alch/alchemy-web3")6const web3 = createAlchemyWeb3(alchemyKey)78//export const helloWorldContract; // export const helloWorldContract;Di atas, kita pertama-tama mengimpor kunci Alchemy dari file .env kita dan kemudian meneruskan alchemyKey kita ke createAlchemyWeb3 untuk membuat titik akhir Alchemy Web3 kita.
Dengan titik akhir ini siap, saatnya untuk memuat kontrak pintar kita!
Memuat kontrak pintar Hello World Anda
Untuk memuat kontrak pintar Hello World Anda, Anda akan memerlukan alamat kontrak dan ABI-nya, yang keduanya dapat ditemukan di Etherscan jika Anda menyelesaikan Bagian 3 dari tutorial ini.
Cara mendapatkan ABI kontrak Anda dari Etherscan
Jika Anda melewati Bagian 3 dari tutorial ini, Anda dapat menggunakan kontrak HelloWorld dengan alamat 0x6f3f635A9762B47954229Ea479b4541eAF402A6A (opens in a new tab). ABI-nya dapat ditemukan di sini (opens in a new tab).
ABI kontrak diperlukan untuk menentukan fungsi mana yang akan dipanggil oleh kontrak serta memastikan bahwa fungsi tersebut akan mengembalikan data dalam format yang Anda harapkan. Setelah kita menyalin ABI kontrak kita, mari simpan sebagai file JSON bernama contract-abi.json di direktori src Anda.
contract-abi.json Anda harus disimpan di folder src Anda.
Berbekal alamat kontrak, ABI, dan titik akhir Alchemy Web3 kita, kita dapat menggunakan metode kontrak (opens in a new tab) untuk memuat instansiasi kontrak pintar kita. Impor ABI kontrak Anda ke dalam file interact.js dan tambahkan alamat kontrak Anda.
1// interact.js // interact.js23const contractABI = require("../contract-abi.json")4const contractAddress = "0x6f3f635A9762B47954229Ea479b4541eAF402A6A"Kita sekarang akhirnya dapat menghapus komentar variabel helloWorldContract kita, dan memuat kontrak pintar menggunakan titik akhir AlchemyWeb3 kita:
1// interact.js // interact.js2export const helloWorldContract = new web3.eth.Contract(3 contractABI,4 contractAddress5)Sebagai rekap, 12 baris pertama dari interact.js Anda sekarang akan terlihat seperti ini:
1// interact.js // interact.js23require("dotenv").config()4const alchemyKey = process.env.REACT_APP_ALCHEMY_KEY5const { createAlchemyWeb3 } = require("@alch/alchemy-web3")6const web3 = createAlchemyWeb3(alchemyKey)78const contractABI = require("../contract-abi.json")9const contractAddress = "0x6f3f635A9762B47954229Ea479b4541eAF402A6A"1011export const helloWorldContract = new web3.eth.Contract(12 contractABI,13 contractAddress14)Tampilkan semuaSekarang setelah kontrak kita dimuat, kita dapat mengimplementasikan fungsi loadCurrentMessage kita!
Mengimplementasikan loadCurrentMessage di file interact.js Anda
Fungsi ini sangat sederhana. Kita akan melakukan panggilan web3 async sederhana untuk membaca dari kontrak kita. Fungsi kita akan mengembalikan pesan yang disimpan di kontrak pintar:
Perbarui loadCurrentMessage di file interact.js Anda menjadi berikut ini:
1// interact.js // interact.js23export const loadCurrentMessage = async () => {4 const message = await helloWorldContract.methods.message().call()5 return message6}Karena kita ingin menampilkan kontrak pintar ini di UI kita, mari perbarui fungsi useEffect di komponen HelloWorld.js kita menjadi berikut ini:
1// HelloWorld.js // HelloWorld.js23//called only once // hanya dipanggil sekali4useEffect(async () => {5 const message = await loadCurrentMessage()6 setMessage(message)7}, [])Catatan, kita hanya ingin loadCurrentMessage kita dipanggil sekali selama render pertama komponen. Kita akan segera mengimplementasikan addSmartContractListener untuk memperbarui UI secara otomatis setelah pesan di kontrak pintar berubah.
Sebelum kita menyelami pendengar kita, mari kita periksa apa yang kita miliki sejauh ini! Simpan file HelloWorld.js dan interact.js Anda, lalu buka http://localhost:3000/ (opens in a new tab)
Anda akan melihat bahwa pesan saat ini tidak lagi mengatakan "No connection to the network." Sebaliknya, ini mencerminkan pesan yang disimpan di kontrak pintar. Keren!
UI Anda sekarang harus mencerminkan pesan yang disimpan di kontrak pintar
Sekarang berbicara tentang pendengar itu...
Implementasikan addSmartContractListener
Jika Anda mengingat kembali file HelloWorld.sol yang kita tulis di Bagian 1 dari seri tutorial ini (opens in a new tab), Anda akan ingat bahwa ada peristiwa kontrak pintar yang disebut UpdatedMessages yang dipancarkan setelah fungsi update kontrak pintar kita dipanggil (lihat baris 9 dan 27):
1// HelloWorld.sol // HelloWorld.sol23// Specifies the version of Solidity, using semantic versioning. // Menentukan versi Solidity, menggunakan semantic versioning.4// Learn more: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma // Pelajari lebih lanjut: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma5pragma solidity ^0.7.3;67// Defines a contract named `HelloWorld`. // Mendefinisikan kontrak bernama `HelloWorld`.8// A contract is a collection of functions and data (its state). Once deployed, a contract resides at a specific address on the Ethereum blockchain. Learn more: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html // Kontrak adalah kumpulan fungsi dan data (state-nya). Setelah disebarkan, kontrak berada di alamat tertentu di blockchain Ethereum. Pelajari lebih lanjut: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html9contract HelloWorld {1011 //Emitted when update function is called // Dikeluarkan saat fungsi update dipanggil12 //Smart contract events are a way for your contract to communicate that something happened on the blockchain to your app front-end, which can be 'listening' for certain events and take action when they happen. // Event kontrak pintar adalah cara bagi kontrak Anda untuk mengomunikasikan bahwa sesuatu telah terjadi di blockchain ke front-end aplikasi Anda, yang dapat 'mendengarkan' event tertentu dan mengambil tindakan saat event tersebut terjadi.13 event UpdatedMessages(string oldStr, string newStr);1415 // Declares a state variable `message` of type `string`. // Mendeklarasikan variabel state `message` dengan tipe `string`.16 // State variables are variables whose values are permanently stored in contract storage. The keyword `public` makes variables accessible from outside a contract and creates a function that other contracts or clients can call to access the value. // Variabel state adalah variabel yang nilainya disimpan secara permanen di penyimpanan kontrak. Kata kunci `public` membuat variabel dapat diakses dari luar kontrak dan membuat fungsi yang dapat dipanggil oleh kontrak atau klien lain untuk mengakses nilainya.17 string public message;1819 // Similar to many class-based object-oriented languages, a constructor is a special function that is only executed upon contract creation. // Mirip dengan banyak bahasa berorientasi objek berbasis kelas, konstruktor adalah fungsi khusus yang hanya dieksekusi saat pembuatan kontrak.20 // Constructors are used to initialize the contract's data. Learn more:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors // Konstruktor digunakan untuk menginisialisasi data kontrak. Pelajari lebih lanjut:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors21 constructor(string memory initMessage) {2223 // Accepts a string argument `initMessage` and sets the value into the contract's `message` storage variable). // Menerima argumen string `initMessage` dan menetapkan nilainya ke dalam variabel penyimpanan `message` kontrak).24 message = initMessage;25 }2627 // A public function that accepts a string argument and updates the `message` storage variable. // Fungsi publik yang menerima argumen string dan memperbarui variabel penyimpanan `message`.28 function update(string memory newMessage) public {29 string memory oldMsg = message;30 message = newMessage;31 emit UpdatedMessages(oldMsg, newMessage);32 }33}Tampilkan semuaPeristiwa kontrak pintar adalah cara bagi kontrak Anda untuk mengomunikasikan bahwa sesuatu terjadi (yaitu, ada peristiwa) di blockchain ke aplikasi front-end Anda, yang dapat 'mendengarkan' peristiwa tertentu dan mengambil tindakan ketika peristiwa itu terjadi.
Fungsi addSmartContractListener akan secara khusus mendengarkan peristiwa UpdatedMessages dari kontrak pintar Hello World kita, dan memperbarui UI kita untuk menampilkan pesan baru.
Ubah addSmartContractListener menjadi berikut ini:
1// HelloWorld.js // HelloWorld.js23function addSmartContractListener() {4 helloWorldContract.events.UpdatedMessages({}, (error, data) => {5 if (error) {6 setStatus("😥 " + error.message)7 } else {8 setMessage(data.returnValues[1])9 setNewMessage("")10 setStatus("🎉 Your message has been updated!")11 }12 })13}Tampilkan semuaMari kita uraikan apa yang terjadi ketika pendengar mendeteksi suatu peristiwa:
- Jika terjadi kesalahan saat peristiwa dipancarkan, itu akan tercermin di UI melalui variabel status
statuskita. - Jika tidak, kita akan menggunakan objek
datayang dikembalikan.data.returnValuesadalah array yang diindeks pada nol di mana elemen pertama dalam array menyimpan pesan sebelumnya dan elemen kedua menyimpan pesan yang diperbarui. Secara keseluruhan, pada peristiwa yang berhasil kita akan mengatur stringmessagekita ke pesan yang diperbarui, menghapus stringnewMessage, dan memperbarui variabel statusstatuskita untuk mencerminkan bahwa pesan baru telah dipublikasikan di kontrak pintar kita.
Terakhir, mari panggil pendengar kita di fungsi useEffect kita sehingga diinisialisasi pada render pertama komponen HelloWorld.js. Secara keseluruhan, fungsi useEffect Anda akan terlihat seperti ini:
1// HelloWorld.js // HelloWorld.js23useEffect(async () => {4 const message = await loadCurrentMessage()5 setMessage(message)6 addSmartContractListener()7}, [])Sekarang setelah kita dapat membaca dari kontrak pintar kita, akan sangat bagus untuk mencari tahu cara menulis ke dalamnya juga! Namun, untuk menulis ke dapp kita, kita harus terlebih dahulu memiliki dompet Ethereum yang terhubung dengannya.
Jadi, selanjutnya kita akan menangani penyiapan dompet Ethereum kita (MetaMask) dan kemudian menghubungkannya ke dapp kita!
Langkah 4: Siapkan dompet Ethereum Anda
Untuk menulis apa pun ke rantai Ethereum, pengguna harus menandatangani transaksi menggunakan kunci pribadi dompet virtual mereka. Untuk tutorial ini, kita akan menggunakan MetaMask (opens in a new tab), dompet virtual di peramban yang digunakan untuk mengelola alamat akun Ethereum Anda, karena ini membuat penandatanganan transaksi ini sangat mudah bagi pengguna akhir.
Jika Anda ingin memahami lebih lanjut tentang cara kerja transaksi di Ethereum, periksa halaman ini dari yayasan Ethereum.
Unduh MetaMask
Anda dapat mengunduh dan membuat akun MetaMask secara gratis di sini (opens in a new tab). Saat Anda membuat akun, atau jika Anda sudah memiliki akun, pastikan untuk beralih ke “Goerli Test Network” di kanan atas (sehingga kita tidak berurusan dengan uang sungguhan).
Tambahkan ether dari Faucet
Untuk menandatangani transaksi di blockchain Ethereum, kita akan membutuhkan beberapa Eth palsu. Untuk mendapatkan Eth Anda dapat pergi ke FaucETH (opens in a new tab) dan masukkan alamat akun Goerli Anda, klik “Request funds”, lalu pilih “Ethereum Testnet Goerli” di dropdown dan terakhir klik tombol “Request funds” lagi. Anda akan melihat Eth di akun MetaMask Anda segera setelahnya!
Periksa Saldo Anda
Untuk memeriksa ulang saldo kita ada di sana, mari buat permintaan eth_getBalance (opens in a new tab) menggunakan alat komposer Alchemy (opens in a new tab). Ini akan mengembalikan jumlah Eth di dompet kita. Setelah Anda memasukkan alamat akun MetaMask Anda dan mengklik “Send Request”, Anda akan melihat respons seperti ini:
1{"jsonrpc": "2.0", "id": 0, "result": "0xde0b6b3a7640000"}CATATAN: Hasil ini dalam wei bukan eth. Wei digunakan sebagai denominasi terkecil dari ether. Konversi dari wei ke eth adalah: 1 eth = 10¹⁸ wei. Jadi jika kita mengonversi 0xde0b6b3a7640000 ke desimal kita mendapatkan 1*10¹⁸ yang sama dengan 1 eth.
Fiuh! Uang palsu kita semuanya ada di sana! 🤑
Langkah 5: Hubungkan MetaMask ke UI Anda
Sekarang setelah dompet MetaMask kita disiapkan, mari hubungkan dapp kita ke sana!
Fungsi connectWallet
Di file interact.js kita, mari implementasikan fungsi connectWallet, yang kemudian dapat kita panggil di komponen HelloWorld.js kita.
Mari ubah connectWallet menjadi berikut ini:
1// interact.js // interact.js23export const connectWallet = async () => {4 if (window.ethereum) {5 try {6 const addressArray = await window.ethereum.request({7 method: "eth_requestAccounts",8 })9 const obj = {10 status: "👆🏽 Write a message in the text-field above.",11 address: addressArray[0],12 }13 return obj14 } catch (err) {15 return {16 address: "",17 status: "😥 " + err.message,18 }19 }20 } else {21 return {22 address: "",23 status: (24 <span>25 <p>26 {" "}27 🦊 <a target="_blank" href={`https://metamask.io/download`}>28 You must install MetaMask, a virtual Ethereum wallet, in your29 browser.30 </a>31 </p>32 </span>33 ),34 }35 }36}Tampilkan semuaJadi apa sebenarnya yang dilakukan oleh blok kode raksasa ini?
Nah, pertama, ia memeriksa apakah window.ethereum diaktifkan di peramban Anda.
window.ethereum adalah API global yang disuntikkan oleh MetaMask dan penyedia dompet lainnya yang memungkinkan situs web untuk meminta akun Ethereum pengguna. Jika disetujui, ia dapat membaca data dari blockchain yang terhubung dengan pengguna, dan menyarankan agar pengguna menandatangani pesan dan transaksi. Periksa dokumen MetaMask (opens in a new tab) untuk info lebih lanjut!
Jika window.ethereum tidak ada, maka itu berarti MetaMask tidak diinstal. Ini menghasilkan objek JSON yang dikembalikan, di mana address yang dikembalikan adalah string kosong, dan objek JSX status menyampaikan bahwa pengguna harus menginstal MetaMask.
Sekarang jika window.ethereum ada, maka saat itulah hal-hal menjadi menarik.
Menggunakan loop try/catch, kita akan mencoba terhubung ke MetaMask dengan memanggil window.ethereum.request({ method: "eth_requestAccounts" }); (opens in a new tab). Memanggil fungsi ini akan membuka MetaMask di peramban, di mana pengguna akan diminta untuk menghubungkan dompet mereka ke dapp Anda.
- Jika pengguna memilih untuk terhubung,
method: "eth_requestAccounts"akan mengembalikan array yang berisi semua alamat akun pengguna yang terhubung ke dapp. Secara keseluruhan, fungsiconnectWalletkita akan mengembalikan objek JSON yang berisiaddresspertama dalam array ini (lihat baris 9) dan pesanstatusyang meminta pengguna untuk menulis pesan ke kontrak pintar. - Jika pengguna menolak koneksi, maka objek JSON akan berisi string kosong untuk
addressyang dikembalikan dan pesanstatusyang mencerminkan bahwa pengguna menolak koneksi.
Sekarang setelah kita menulis fungsi connectWallet ini, langkah selanjutnya adalah memanggilnya ke komponen HelloWorld.js kita.
Tambahkan fungsi connectWallet ke Komponen UI HelloWorld.js Anda
Navigasikan ke fungsi connectWalletPressed di HelloWorld.js, dan perbarui menjadi berikut ini:
1// HelloWorld.js // HelloWorld.js23const connectWalletPressed = async () => {4 const walletResponse = await connectWallet()5 setStatus(walletResponse.status)6 setWallet(walletResponse.address)7}Perhatikan bagaimana sebagian besar fungsionalitas kita diabstraksikan dari komponen HelloWorld.js kita dari file interact.js? Ini agar kita mematuhi paradigma M-V-C!
Di connectWalletPressed, kita cukup melakukan panggilan await ke fungsi connectWallet yang kita impor, dan menggunakan responsnya, kita memperbarui variabel status dan walletAddress kita melalui hook status mereka.
Sekarang, mari simpan kedua file (HelloWorld.js dan interact.js) dan uji UI kita sejauh ini.
Buka peramban Anda di halaman http://localhost:3000/ (opens in a new tab), dan tekan tombol "Connect Wallet" di kanan atas halaman.
Jika Anda telah menginstal MetaMask, Anda akan diminta untuk menghubungkan dompet Anda ke dapp Anda. Terima undangan untuk terhubung.
Anda akan melihat bahwa tombol dompet sekarang mencerminkan bahwa alamat Anda terhubung! Yasssss 🔥
Selanjutnya, coba segarkan halaman... ini aneh. Tombol dompet kita meminta kita untuk menghubungkan MetaMask, meskipun sudah terhubung...
Namun, jangan takut! Kita dapat dengan mudah mengatasinya dengan mengimplementasikan getCurrentWalletConnected, yang akan memeriksa apakah alamat sudah terhubung ke dapp kita dan memperbarui UI kita sesuai dengan itu!
Fungsi getCurrentWalletConnected
Perbarui fungsi getCurrentWalletConnected Anda di file interact.js menjadi berikut ini:
1// interact.js // interact.js23export const getCurrentWalletConnected = async () => {4 if (window.ethereum) {5 try {6 const addressArray = await window.ethereum.request({7 method: "eth_accounts",8 })9 if (addressArray.length > 0) {10 return {11 address: addressArray[0],12 status: "👆🏽 Write a message in the text-field above.",13 }14 } else {15 return {16 address: "",17 status: "🦊 Connect to MetaMask using the top right button.",18 }19 }20 } catch (err) {21 return {22 address: "",23 status: "😥 " + err.message,24 }25 }26 } else {27 return {28 address: "",29 status: (30 <span>31 <p>32 {" "}33 🦊 <a target="_blank" href={`https://metamask.io/download`}>34 You must install MetaMask, a virtual Ethereum wallet, in your35 browser.36 </a>37 </p>38 </span>39 ),40 }41 }42}Tampilkan semuaKode ini sangat mirip dengan fungsi connectWallet yang baru saja kita tulis di langkah sebelumnya.
Perbedaan utamanya adalah alih-alih memanggil metode eth_requestAccounts, yang membuka MetaMask bagi pengguna untuk menghubungkan dompet mereka, di sini kita memanggil metode eth_accounts, yang hanya mengembalikan array yang berisi alamat MetaMask yang saat ini terhubung ke dapp kita.
Untuk melihat fungsi ini beraksi, mari panggil di fungsi useEffect dari komponen HelloWorld.js kita:
1// HelloWorld.js // HelloWorld.js23useEffect(async () => {4 const message = await loadCurrentMessage()5 setMessage(message)6 addSmartContractListener()78 const { address, status } = await getCurrentWalletConnected()9 setWallet(address)10 setStatus(status)11}, [])Tampilkan semuaPerhatikan, kita menggunakan respons dari panggilan kita ke getCurrentWalletConnected untuk memperbarui variabel status walletAddress dan status kita.
Sekarang setelah Anda menambahkan kode ini, mari coba segarkan jendela peramban kita.
Bagussss! Tombol tersebut harus mengatakan bahwa Anda terhubung, dan menampilkan pratinjau alamat dompet Anda yang terhubung - bahkan setelah Anda menyegarkan!
Implementasikan addWalletListener
Langkah terakhir dalam penyiapan dompet dapp kita adalah mengimplementasikan pendengar dompet sehingga UI kita diperbarui ketika status dompet kita berubah, seperti ketika pengguna memutuskan sambungan atau beralih akun.
Di file HelloWorld.js Anda, ubah fungsi addWalletListener Anda sebagai berikut:
1// HelloWorld.js // HelloWorld.js23function addWalletListener() {4 if (window.ethereum) {5 window.ethereum.on("accountsChanged", (accounts) => {6 if (accounts.length > 0) {7 setWallet(accounts[0])8 setStatus("👆🏽 Write a message in the text-field above.")9 } else {10 setWallet("")11 setStatus("🦊 Connect to MetaMask using the top right button.")12 }13 })14 } else {15 setStatus(16 <p>17 {" "}18 🦊 <a target="_blank" href={`https://metamask.io/download`}>19 You must install MetaMask, a virtual Ethereum wallet, in your browser.20 </a>21 </p>22 )23 }24}Tampilkan semuaSaya yakin Anda bahkan tidak memerlukan bantuan kami untuk memahami apa yang terjadi di sini pada titik ini, tetapi untuk tujuan ketelitian, mari kita uraikan dengan cepat:
- Pertama, fungsi kita memeriksa apakah
window.ethereumdiaktifkan (yaitu, MetaMask diinstal).- Jika tidak, kita cukup mengatur variabel status
statuskita ke string JSX yang meminta pengguna untuk menginstal MetaMask. - Jika diaktifkan, kita menyiapkan pendengar
window.ethereum.on("accountsChanged")pada baris 3 yang mendengarkan perubahan status di dompet MetaMask, yang mencakup ketika pengguna menghubungkan akun tambahan ke dapp, beralih akun, atau memutuskan sambungan akun. Jika ada setidaknya satu akun yang terhubung, variabel statuswalletAddressdiperbarui sebagai akun pertama dalam arrayaccountsyang dikembalikan oleh pendengar. Jika tidak,walletAddressdiatur sebagai string kosong.
- Jika tidak, kita cukup mengatur variabel status
Terakhir namun tidak kalah pentingnya, kita harus memanggilnya di fungsi useEffect kita:
1// HelloWorld.js // HelloWorld.js23useEffect(async () => {4 const message = await loadCurrentMessage()5 setMessage(message)6 addSmartContractListener()78 const { address, status } = await getCurrentWalletConnected()9 setWallet(address)10 setStatus(status)1112 addWalletListener()13}, [])Tampilkan semuaDan itu saja! Kita telah berhasil menyelesaikan pemrograman semua fungsionalitas dompet kita! Sekarang ke tugas terakhir kita: memperbarui pesan yang disimpan di kontrak pintar kita!
Langkah 6: Implementasikan fungsi updateMessage
Baiklah teman-teman, kita telah tiba di tahap akhir! Di updateMessage dari file interact.js Anda, kita akan melakukan hal berikut:
- Pastikan pesan yang ingin kita publikasikan di kontrak pintar kita valid
- Tandatangani transaksi kita menggunakan MetaMask
- Panggil fungsi ini dari komponen frontend
HelloWorld.jskita
Ini tidak akan memakan waktu lama; mari selesaikan dapp ini!
Penanganan kesalahan input
Tentu saja, masuk akal untuk memiliki semacam penanganan kesalahan input di awal fungsi.
Kita akan menginginkan fungsi kita untuk kembali lebih awal jika tidak ada ekstensi MetaMask yang diinstal, tidak ada dompet yang terhubung (yaitu, address yang diteruskan adalah string kosong), atau message adalah string kosong. Mari tambahkan penanganan kesalahan berikut ke updateMessage:
1// interact.js // interact.js23export const updateMessage = async (address, message) => {4 if (!window.ethereum || address === null) {5 return {6 status:7 "💡 Connect your MetaMask wallet to update the message on the blockchain.",8 }9 }1011 if (message.trim() === "") {12 return {13 status: "❌ Your message cannot be an empty string.",14 }15 }16}Tampilkan semuaSekarang setelah memiliki penanganan kesalahan input yang tepat, saatnya untuk menandatangani transaksi melalui MetaMask!
Menandatangani transaksi kita
Jika Anda sudah terbiasa dengan transaksi Ethereum web3 tradisional, kode yang kita tulis selanjutnya akan sangat familier. Di bawah kode penanganan kesalahan input Anda, tambahkan yang berikut ini ke updateMessage:
1// interact.js // interact.js23//set up transaction parameters // menyiapkan parameter transaksi4const transactionParameters = {5 to: contractAddress, // Required except during contract publications. // Diperlukan kecuali selama publikasi kontrak.6 from: address, // must match user's active address. // harus cocok dengan alamat aktif pengguna.7 data: helloWorldContract.methods.update(message).encodeABI(),8}910//sign the transaction // menandatangani transaksi11try {12 const txHash = await window.ethereum.request({13 method: "eth_sendTransaction",14 params: [transactionParameters],15 })16 return {17 status: (18 <span>19 ✅{" "}20 <a target="_blank" href={`https://goerli.etherscan.io/tx/${txHash}`}>21 View the status of your transaction on Etherscan!22 </a>23 <br />24 ℹ️ Once the transaction is verified by the network, the message will be25 updated automatically.26 </span>27 ),28 }29} catch (error) {30 return {31 status: "😥 " + error.message,32 }33}Tampilkan semuaMari kita uraikan apa yang terjadi. Pertama, kita menyiapkan parameter transaksi kita, di mana:
tomenentukan alamat penerima (kontrak pintar kita)frommenentukan penandatangan transaksi, variabeladdressyang kita teruskan ke fungsi kitadataberisi panggilan ke metodeupdatekontrak pintar Hello World kita, menerima variabel stringmessagekita sebagai input
Kemudian, kita melakukan panggilan await, window.ethereum.request, di mana kita meminta MetaMask untuk menandatangani transaksi. Perhatikan, pada baris 11 dan 12, kita menentukan metode eth kita, eth_sendTransaction dan meneruskan transactionParameters kita.
Pada titik ini, MetaMask akan terbuka di peramban, dan meminta pengguna untuk menandatangani atau menolak transaksi.
- Jika transaksi berhasil, fungsi akan mengembalikan objek JSON di mana string JSX
statusmeminta pengguna untuk memeriksa Etherscan untuk informasi lebih lanjut tentang transaksi mereka. - Jika transaksi gagal, fungsi akan mengembalikan objek JSON di mana string
statusmenyampaikan pesan kesalahan.
Secara keseluruhan, fungsi updateMessage kita akan terlihat seperti ini:
1// interact.js // interact.js23export const updateMessage = async (address, message) => {4 //input error handling // penanganan kesalahan input5 if (!window.ethereum || address === null) {6 return {7 status:8 "💡 Connect your MetaMask wallet to update the message on the blockchain.",9 }10 }1112 if (message.trim() === "") {13 return {14 status: "❌ Your message cannot be an empty string.",15 }16 }1718 //set up transaction parameters // menyiapkan parameter transaksi19 const transactionParameters = {20 to: contractAddress, // Required except during contract publications. // Diperlukan kecuali selama publikasi kontrak.21 from: address, // must match user's active address. // harus cocok dengan alamat aktif pengguna.22 data: helloWorldContract.methods.update(message).encodeABI(),23 }2425 //sign the transaction // menandatangani transaksi26 try {27 const txHash = await window.ethereum.request({28 method: "eth_sendTransaction",29 params: [transactionParameters],30 })31 return {32 status: (33 <span>34 ✅{" "}35 <a target="_blank" href={`https://goerli.etherscan.io/tx/${txHash}`}>36 View the status of your transaction on Etherscan!37 </a>38 <br />39 ℹ️ Once the transaction is verified by the network, the message will40 be updated automatically.41 </span>42 ),43 }44 } catch (error) {45 return {46 status: "😥 " + error.message,47 }48 }49}Tampilkan semuaTerakhir namun tidak kalah pentingnya, kita perlu menghubungkan fungsi updateMessage kita ke komponen HelloWorld.js kita.
Hubungkan updateMessage ke frontend HelloWorld.js
Fungsi onUpdatePressed kita harus melakukan panggilan await ke fungsi updateMessage yang diimpor dan memodifikasi variabel status status untuk mencerminkan apakah transaksi kita berhasil atau gagal:
1// HelloWorld.js // HelloWorld.js23const onUpdatePressed = async () => {4 const { status } = await updateMessage(walletAddress, newMessage)5 setStatus(status)6}Ini sangat bersih dan sederhana. Dan tebak apa... DAPP ANDA SELESAI!!!
Silakan dan uji tombol Update!
Buat dapp kustom Anda sendiri
Wooooo, Anda berhasil mencapai akhir tutorial! Sebagai rekap, Anda telah mempelajari cara:
- Menghubungkan dompet MetaMask ke proyek dapp Anda
- Membaca data dari kontrak pintar Anda menggunakan API Alchemy Web3 (opens in a new tab)
- Menandatangani transaksi Ethereum menggunakan MetaMask
Sekarang Anda sepenuhnya siap untuk menerapkan keterampilan dari tutorial ini untuk membangun proyek dapp kustom Anda sendiri! Seperti biasa, jika Anda memiliki pertanyaan, jangan ragu untuk menghubungi kami untuk mendapatkan bantuan di Discord Alchemy (opens in a new tab). 🧙♂️
Setelah Anda menyelesaikan tutorial ini, beri tahu kami bagaimana pengalaman Anda atau jika Anda memiliki umpan balik dengan menandai kami di Twitter @alchemyplatform (opens in a new tab)!
Pembaruan terakhir halaman: 26 Februari 2026





