Ana içeriğe geç

Yeni Başlayanlar İçin Merhaba Dünya Akıllı Sözleşmesi - FullStack

solidityhardhatalchemyakıllı sözleşmelerdağıtmablok bulucuön yüzİşlemler
Acemi
nstrike2
25 Ekim 2021
37 dakikalık okuma minute read

Bu rehber, blokzincir geliştirme konusunda yeniyseniz, nereden başlayacağınızı bilmiyorsanız veya akıllı sözleşmeleri nasıl dağıtacağınızı ya da onlarla nasıl etkileşim kuracağınızı bilmiyorsanız tam size göre. Size, Goerli test ağında MetaMask(opens in a new tab), Solidity(opens in a new tab), Hardhat(opens in a new tab) ve Alchemy(opens in a new tab)'yi kullanarak basit bir akıllı sözleşme oluşturmayı ve dağıtmayı öğreteceğiz.

Bu öğreticiyi tamamlamak için bir Alchemy hesabına ihtiyacınız olacak. Ücretsiz bir hesap açmak için kaydolun(opens in a new tab).

Herhangi bir noktada sorunuz olursa, Alchemy Discord(opens in a new tab)'unu ziyaret etmekten çekinmeyin!

1. Bölüm - Hardhat Kullanarak Akıllı Sözleşmenizi Oluşturma ve Dağıtma

Ethereum ağına bağlanın

Ethereum zincirine istek göndermenin birçok yolu vardır. Kolay anlaşılabilmesi için düğümü kendimiz çalıştırmadan Ethereum zinciriyle bağlantı kurabilmemize olanak tanıyan bir blokzincir geliştirme platformu ve API'si olan Alchemy'de açtığımız ücretsiz bir hesabı kullanacağız. Alchemy ayrıca, akıllı sözleşme dağıtımımızda arka planda neler olup bittiğini anlamak için bu öğreticide yararlanacağımız izleme ve analitiğe yönelik geliştirici araçlarına sahiptir.

Uygulamanızı ve API anahtarınızı oluşturun

Bir Alchemy hesabı oluşturduktan sonra, bir uygulama yaratarak bir API anahtarı oluşturabilirsiniz. Bu Goerli test ağına taleplerde bulunmanızı sağlayacaktır. Test ağlarıyla ilgili pek bilginiz yoksa Alchemy'nin ağ seçme rehberini okuyabilirsiniz(opens in a new tab).

Alchemy'nin sayfasında Uygulamalar seçeneğini bulun ve aşağı inip Uygulama Oluştur'a tıklayın.

Merhaba dünya uygulama oluşturma

Uygulamanıza "Merhaba Dünya" ismini verin ve kısa bir açıklama yazın. Ortam olarak Hazırlama'yı ve ağ olarak da Goerli'yi seçin.

merhaba dünya görüntüleme uygulamasını oluşturma

Not: Goerli'yi seçmezseniz bu öğretici çalışmaz.

Uygulama oluştur'a tıklayın. Uygulamanız aşağıdaki tabloda görünecektir.

Bir Ethereum hesabı oluşturun

İşlem göndermek ve almak için bir Ethereum hesabına ihtiyacınız vardır. Kullanıcıların Ethereum hesap adreslerini yönetmelerini sağlayan bir sanal tarayıcı cüzdanı olan MetaMask'i kullanacağız.

Buradan(opens in a new tab) ücretsiz olarak bir MetaMask hesabı indirebilir ve oluşturabilirsiniz. Bir hesap oluştururken ya da zaten bir hesabınız varsa, sağ üstten "Goerli Test Ağına" geçin (bu sayede gerçek parayla denemeler yapmayız).

Adım 4: Bir Musluktan ether ekleyin

Akıllı sözleşmenizi test ağına dağıtmak için biraz sahte ETH'ye ihtiyacınız olacak. Goerli ağında ETH alabilmek için bir Goerli musluğuna gidin ve Goerli hesabınızın adresini girin. Goerli musluklarının son zamanlarda biraz güvenilmez olduğunu da dikkate alın; test ağları sayfası'ndan denenebilecek seçeneklerin listesine göz atın:

Not: Ağ sıkışıklığı sebebiyle bu biraz zaman alabilir. ``

Adım 5: Bakiyenizi kontrol edin

ETH'nin cüzdanınızda olduğundan emin olmak için Alchemy'nin derleyici aracını(opens in a new tab) kullanarak bir eth_getBalance(opens in a new tab) isteği oluşturalım. Bu, cüzdanımızdaki ETH miktarını döndürür. Daha fazla bilgi edinmek için Alchemy'nin derleyici aracını kullanma hakkındaki kısa öğreticisine(opens in a new tab) göz atabilirsiniz.

Metamask hesap adresinizi girin ve İstek Gönder'e tıklayın. Aşağıdaki ufak kod parçası gibi bir cevap göreceksiniz.

1{ "jsonrpc": "2.0", "id": 0, "result": "0x2B5E3AF16B1880000" }
Kopyala

Not: Bu sonuç ETH değil, wei cinsindendir. Wei, ether'ın en küçük birimi olarak kullanılır.

Vay be! Tüm sahte paramız yerli yerinde.

Adım 6: Projemizi başlatın

Önce, projemiz için bir klasör oluşturmamız gerekecek. Komut satırınıza gidin ve aşağıdakini girin.

1mkdir hello-world
2cd hello-world

Artık proje klasörümüzün içinde olduğumuza göre, projeyi başlatmak için npm init kullanacağız.

Eğer npm'i hala yüklemediyseniz Node.js ve npm'i yüklemek için bu talimatları uygulayın(opens in a new tab).

Başlangıç sorularını nasıl cevapladığınız bu öğreticinin amacıyla alakasızdır. Biz referans olarak bu şekilde yaptık:

1package name: (hello-world)
2version: (1.0.0)
3description: hello world smart contract
4entry point: (index.js)
5test command:
6git repository:
7keywords:
8author:
9license: (ISC)
10
11About to write to /Users/.../.../.../hello-world/package.json:
12
13{
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}
Tümünü göster

package.json'ı onayladıktan sonra hazırız!

7. Adım: Hardhat'i indirin

Hardhat, Ethereum yazılımınızı derlemek, dağıtmak, test etmek ve hatalarını ayıklamak için bir geliştirme ortamıdır. Bu geliştiricilere canlı zincirde dağıtmadan önce akıllı sözleşmelerini ve merkeziyetsiz uygulamalarını geliştirirken yardımcı olur.

hello-world projemizin içinde şunu yürütün:

1npm install --save-dev hardhat

Kurulum talimatları(opens in a new tab) hakkında daha fazla ayrıntı için bu sayfaya göz atın.

Adım 8: Hardhat projesi oluşturun

hello-world proje klasörümüzde aşağıdaki komutu çalıştırın:

1npx hardhat

Daha sonra bir karşılama mesajı ve ne yapmak istediğinizi seçme seçeneği görmelisiniz. "create an empty hardhat.config.js"yi (boş bir hardhat.config.js oluştur) seçin:

1888 888 888 888 888
2888 888 888 888 888
3888 888 888 888 888
48888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888
5888 888 "88b 888P" d88" 888 888 "88b "88b 888
6888 888 .d888888 888 888 888 888 888 .d888888 888
7888 888 888 888 888 Y88b 888 888 888 888 888 Y88b.
8888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888
9
10👷 Welcome to Hardhat v2.0.11 👷‍
11
12What do you want to do? …
13Create a sample project
14❯ Create an empty hardhat.config.js
15Quit
Tümünü göster

Bu, projenin içinde bir hardhat.config.js dosyası oluşturacaktır. Bunu, bu öğreticinin içinde daha sonra projemizin kurulumunu özelleştirmek için kullanacağız.

Adım 9: Proje klasörleri ekleyin

Bu projeyi düzenli tutmak için iki yeni klasör daha oluşturalım. Komut satırına hello-world projenizin kök rehberine gidip şunları yazın:

1mkdir contracts
2mkdir scripts
  • contracts/ merhaba dünya akıllı sözleşme kod dosyamızı tutacağımız yerdir
  • scripts/, sözleşmemizi dağıtmak ve etkileşim kurmak için komut dosyalarını tutacağımız yerdir

Adım 10: Sözleşmemizi yazın

Kendinize, ne zaman kod yazmaya başlayacağız diye mi soruyorsunuz? İşte o vakit geldi!

En sevdiğiniz düzenleyicide hello-world projenizi açın. Akıllı sözleşmeler genelde Solidity'de yazılır, biz de akıllı sözleşmemizi yazmak için onu kullanacağız.

  1. contracts klasörüne gidin ve HelloWorld.sol adında bir dosya oluşturun
  2. Aşağıda bu öğreticide kullanacağımız örnek bir Hello World akıllı sözleşmesi var. Aşağıdaki içerikleri HelloWorld.sol dosyasına kopyalayın.

Not: Bu sözleşmenin ne yaptığını anlayabilmek için yorumları okuduğunuzdan emin olun.

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#pragma
3pragma solidity >=0.7.3;
4
5// 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.html
7contract HelloWorld {
8
9 //Emitted when update function is called
10 //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);
12
13 // 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;
16
17 // 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#constructors
19 constructor(string memory initMessage) {
20
21 // Accepts a string argument `initMessage` and sets the value into the contract's `message` storage variable).
22 message = initMessage;
23 }
24
25 // 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}
Tümünü göster

Bu, oluşturma aşaması tamamlandığında bir mesaj depolayan temel bir akıllı sözleşmedir. update fonksiyonunu kullanarak bu akıllı sözleşmeyi güncelleyebiliriz.

Adım 11: MetaMask ve Alchemy'i projenize bağlayın

Bir MetaMask cüzdanı ile Alchemy hesabı oluşturduk ve akıllı sözleşmemizi yazdık, şimdi üçünü birleştirme zamanı.

Cüzdanınızdan gönderilen her işlem kendi benzersiz özel anahtarınızı kullanan bir imzaya ihtiyaç duyar. Programımıza bu izni sağlamak için özel anahtarımızı bir ortam dosyasında güvenle saklayabiliriz. Ayrıca burada, Alchemy için bir API anahtarı da depolayacağız.

İşlem gönderme hakkında daha fazla bilgi edinmek için web3 kullanarak işlem gönderme ile ilgili bu öğreticiye(opens in a new tab) göz atın.

İlk önce dotenv paketini proje dizininize kurun:

1npm install dotenv --save

Sonra, projenin kök rehberinde bir .env dosyası oluşturun. MetaMask özel anahtarınızı ve HTTP Alchemy API URL'nizi bu dosyaya ekleyin.

Ortam dosyanızın adı .env olmak zorundadır, aksi takdirde ortam dosyası olarak tanınmaz.

Dosyanıza process.env, .env-custom ya da başka bir isim vermeyin.

.env dosyanız şu şekilde görünmelidir:

1API_URL = "https://eth-goerli.alchemyapi.io/v2/your-api-key"
2PRIVATE_KEY = "your-metamask-private-key"

Bunları kodumuza gerçekten bağlamak için, adım 13'te hardhat.config.js dosyamızda bu değişkenlere başvuracağız.

Adım 12: Ethers.js'yi kurun

Ethers.js, standart JSON-RPC yöntemlerini(opens in a new tab) daha kullanıcı dostu yöntemlerle birleştirerek Ethereum'la etkileşimde bulunmayı ve Ethereum'a istek göndermeyi kolaylaştıran bir kütüphanedir.

Hardhat, ek araçlar ve daha fazla işlevsellik için eklentiler(opens in a new tab) kullanmamıza olanak tanır. Sözleşme dağıtımı için Ethers eklentisinden(opens in a new tab) yararlanacağız.

Proje klasörünüzde şunu yazın:

npm install --save-dev @nomiclabs/hardhat-ethers "ethers@^5.0.0"

Adım 13: hardhat.config.js'yi güncelleyin

Şimdiye kadar birkaç bağımlılık ve eklenti ekledik, şimdi projemizin bunların hepsini tanıması için hardhat.config.js'yi güncellememiz gerekiyor.

hardhat.config.js dosyanızı şöyle görünecek şekilde güncelleyin:

1/**
2 * @type import('hardhat/config').HardhatUserConfig
3 */
4
5require("dotenv").config()
6require("@nomiclabs/hardhat-ethers")
7
8const { API_URL, PRIVATE_KEY } = process.env
9
10module.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}
Tümünü göster

Adım 14: Sözleşmemizi derleyin

Şimdiye kadar yaptığımız her şeyin çalıştığından emin olmak için sözleşmemizi derleyelim. compile görevi, yerleşik hardhat görevlerden biridir.

Komut satırından şunu yürütün:

npx hardhat compile

SPDX license identifier not provided in source file uyarısı alabilirsiniz, ancak bunun için endişelenmenize gerek yok, geri kalan her şey düzgün olacaktır! Düzgün değilse, istediğiniz zaman Alchemy discord(opens in a new tab)'da mesaj gönderebilirsiniz.

Adım 15: Dağıtım komut dosyamızı yazın

Artık sözleşmemiz yazıldığına ve yapılandırma dosyamız kullanıma hazır olduğuna göre, sözleşme dağıtım komut dosyanızı yazmanın zamanı geldi.

scripts/ klasörüne gidin ve aşağıdaki içeriği ekleyerek deploy.js adlı yeni bir dosya oluşturun:

1async function main() {
2 const HelloWorld = await ethers.getContractFactory("HelloWorld")
3
4 // Start deployment, returning a promise that resolves to a contract object
5 const hello_world = await HelloWorld.deploy("Hello World!")
6 console.log("Contract deployed to address:", hello_world.address)
7}
8
9main()
10 .then(() => process.exit(0))
11 .catch((error) => {
12 console.error(error)
13 process.exit(1)
14 })
Tümünü göster

Hardhat, bu kod satırlarının her birinin ne işe yaradığını Sözleşme öğreticisinde(opens in a new tab) harika bir şekilde açıklıyor, Hardhat açıklamalarını buraya aktardık.

1const HelloWorld = await ethers.getContractFactory("HelloWorld")

Ethers.js'deki bir ContractFactory, yeni akıllı sözleşmeleri dağıtmak için kullanılan bir soyutlamadır, bu nedenle HelloWorld, merhaba dünya sözleşmemizin örnekleri için bir fabrika(opens in a new tab)'dır. hardhat-ethers eklentisini kullanırken ContractFactory ve Contract örnekleri varsayılan olarak ilk imzalayana (sahip) bağlanır.

1const hello_world = await HelloWorld.deploy()

Bir ContractFactory üzerinde deploy() öğesinin çağrılması, dağıtımı başlatır ve Contract nesnesi olarak çözümlenen bir Promise döndürür. Bu, akıllı sözleşme fonksiyonlarımızın her biri için bir yöntemi olan nesnedir.

Adım 16: Sözleşmemizi dağıtın

Sonunda akıllı sözleşmemizi uygulamaya hazırız! Komut satırına gidin ve şunu yürütün:

npx hardhat run scripts/deploy.js --network goerli

Daha sonra şöyle bir şey görmelisiniz:

Contract deployed to address: 0x6cd7d44516a20882cEa2DE9f205bF401c0d23570

Bu adresi lütfen kaydedin. Öğreticide daha sonra kullanacağız.

Goerli etherscan(opens in a new tab)'e gider ve sözleşme adresimizi aratırsak başarıyla dağıtılmış olduğunu görürüz. İşlem şunun gibi gözükecektir:

From adresi MetaMask hesap adresinizle eşleşmelidir ve To adresi Sözleşme Oluşturma ifadesini barındıracaktır. İşleme tıklarsak To alanında sözleşme adresimizi görürüz.

Tebrikler! Az önce Ethereum test ağına bir akıllı sözleşme dağıttınız.

Perde arkasında neler olduğunu anlamak için Alchemy gösterge panelimizde(opens in a new tab) Explorer (Gezgin) sekmesine gidelim. Birden fazla Alchemy uygulamanız varsa, uygulamaya göre filtreleme yaptığınızdan ve Merhaba Dünya'yı seçtiğinizden emin olun.

Burada, .deploy() fonksiyonunu çağırdığımızda Hardhat/Ethers'ın bizim için arka planda oluşturduğu bir avuç JSON-RPC yöntemini göreceksiniz. Buradaki iki önemli yöntem, akıllı sözleşmemizi Goerli zincirine yazma isteği olan eth_sendRawTransaction(opens in a new tab) ve karma değerine göre işlemimiz hakkındaki bilgileri okuma isteği olan eth_getTransactionByHash(opens in a new tab) öğeleridir. İşlem gönderme hakkında daha fazla bilgi edinmek için Web3 kullanarak işlem göndermeyle ilgili öğreticimize göz atın.

2. Bölüm: Akıllı Sözleşmenizle etkileşime geçin

Akıllı sözleşmemizi Goerli ağına başarılı bir şekilde dağıttığımıza göre, artık sözleşmeyle nasıl etkileşim kuracağımızı öğrenebiliriz.

Bir interact.js dosyası oluşturun

Bu etkileşim komut dosyamızı yazacağımız dosyadır. Burada, daha önce 1.Bölüm'de yüklemiş olduğunuz Ethers.js kütüphanesini kullancağız.

scripts/ dosyasının içinde interact.js adında yeni bir dosya oluşturun ve aşağıdaki kodu ekleyin:

1// interact.js
2
3const API_KEY = process.env.API_KEY
4const PRIVATE_KEY = process.env.PRIVATE_KEY
5const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS

.env dosyanızı güncelleyin

Yeni ortam değişkenleri kullanacağımız için bu değişkenleri daha önce oluşturduğumuz .env dosyasında tanımlayacağız.

Alchemy API_KEY'imiz ve akıllı sözleşmenizin dağıtıldığı yer olan CONTRACT_ADDRESS için bir tanım eklememiz gerekecektir.

.env aşağıdaki gibi görünmelidir:

# .env
API_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>"

Sözleşme ABI'nizi alın

Sözleşme , akıllı sözleşmemizle etkileşim kurmak için kullanılan arayüzdür. Hardhat otomatik olarak bir ABI oluşturur ve HelloWorld.json'un içine kaydeder. ABI'yi kullanmak için interact.js dosyamıza aşağıdaki kod satırlarını ekleyerek içeriği ayrıştırmamız gerekir:

1// interact.js
2const contract = require("../artifacts/contracts/HelloWorld.sol/HelloWorld.json")

ABI'yi görmek istiyorsanız onu konsolunuza yazdırabilirsiniz:

1console.log(JSON.stringify(contract.abi))

ABI'nizin konsola yazdırıldığını görmek için terminalinize gidin ve şunu çalıştırın:

npx hardhat run scripts/interact.js

Sözleşmenizin bir örneğini oluşturun

Sözleşmenizle etkileşim kurmak için kodumuzda bir sözleşme örneği oluşturmamız gerekir. Bunu Ethers.js ile yapmak için üç konseptle çalışacağız:

  1. Sağlayıcı - size blockzincir için okuma ve yazma erişimi veren bir düğüm sağlayıcısıdır
  2. İmzalayıcı - işlem imzalayabilen bir Ethereum hesabını gösterir
  3. Sözleşme - zincir üstünde dağıtılmış olan spesifik bir sözleşmeyi temsil eden bir Ethers.js objesidir

Sözleşme örneğimizi oluşturmak için önceki adımdaki sözleşme ABI'mizi kullanacağız:

1// interact.js
2
3// Provider
4const alchemyProvider = new ethers.providers.AlchemyProvider(
5 (network = "goerli"),
6 API_KEY
7)
8
9// Signer
10const signer = new ethers.Wallet(PRIVATE_KEY, alchemyProvider)
11
12// Contract
13const helloWorldContract = new ethers.Contract(
14 CONTRACT_ADDRESS,
15 contract.abi,
16 signer
17)
Tümünü göster

Sağlayıcı, İmzalayıcı ve Sözleşmelerle ilgili ethers.js dokümanlarından(opens in a new tab) daha fazla bilgi edinebilirsiniz.

Başlangıç mesajını okuyun

Sözleşmemizi initMessage = "Hello world!" ile dağıttığımızı hatırlıyor musunuz? Şimdi akıllı sözleşmemizde depolanmış olan bu mesajı okuyacağız ve konsola yazdıracağız.

JavaScript'te ağlarla etkileşim kurulurken asenkronize fonksiyonlar kullanılır. Asenkronize fonksiyonlarla ilgili daha fazla bilgi edinmek için bu medium makalesini okuyun(opens in a new tab).

Akıllı sözleşmemizdeki message fonksiyonunu çağırmak için aşağıdaki kodu kullanın ve başlangıç mesajını okuyun:

1// interact.js
2
3// ...
4
5async function main() {
6 const message = await helloWorldContract.message()
7 console.log("The message is: " + message)
8}
9main()
Tümünü göster

Dosyayı terminaldeki npx hardhat run scripts/interact.js öğesini kullanarak çalıştırdıktan sonra şu yanıtı görmeliyiz:

1The message is: Hello world!

Tebrikler! Az önce Ethereum blokzincirinden başarıyla bir akıllı sözleşme verisi okudunuz, bravo!

Mesajı güncelleyin

Sadece mesajı okumak yerine, update fonksiyonunu kullanarak akıllı sözleşmemizde kayıtlı olan mesajı güncelleyebiliriz! Oldukça havalı, değil mi?

Bu mesajı güncellemek için somutlaşmış sözleşme nesnemizde doğrudan update fonksiyonunu çağırabiliriz:

1// interact.js
2
3// ...
4
5async function main() {
6 const message = await helloWorldContract.message()
7 console.log("The message is: " + message)
8
9 console.log("Updating the message...")
10 const tx = await helloWorldContract.update("This is the new message.")
11 await tx.wait()
12}
13main()
Tümünü göster
  1. satırda dönen işlem nesnesi için .wait() çağrısını yaptığımızı not alın. Bunu yapmak, komut dosyamızın fonksiyondan çıkmadan önce işlemin blokzincirde basılmasını beklediğinden emin olmamızı sağlar. Eğer .wait() çağrısı dahil edilmemişse komut dosyası, sözleşmedeki güncellenmiş message değerini görmeyebilir.

Yeni mesajı okuyun

Güncellenmiş message değerini okumak için önceki adımı tekrar edebilmelisiniz. Bir saniye durun ve yeni değeri yazdırabilmek için gerekli değişiklikleri yapıp yapamadığınıza bakın!

Eğer ipucuna ihtiyacınız varsa, bu noktada interact.js dosyanız bu şekilde görünmelidir:

1// interact.js
2
3const API_KEY = process.env.API_KEY
4const PRIVATE_KEY = process.env.PRIVATE_KEY
5const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS
6
7const contract = require("../artifacts/contracts/HelloWorld.sol/HelloWorld.json")
8
9// provider - Alchemy
10const alchemyProvider = new ethers.providers.AlchemyProvider(
11 (network = "goerli"),
12 API_KEY
13)
14
15// signer - you
16const signer = new ethers.Wallet(PRIVATE_KEY, alchemyProvider)
17
18// contract instance
19const helloWorldContract = new ethers.Contract(
20 CONTRACT_ADDRESS,
21 contract.abi,
22 signer
23)
24
25async function main() {
26 const message = await helloWorldContract.message()
27 console.log("The message is: " + message)
28
29 console.log("Updating the message...")
30 const tx = await helloWorldContract.update("this is the new message")
31 await tx.wait()
32
33 const newMessage = await helloWorldContract.message()
34 console.log("The new message is: " + newMessage)
35}
36
37main()
Tümünü göster

Şimdi sadece komut dosyasını çalıştırın; eski mesajı, güncelleme durumunu ve yeni mesajı terminalinizde yazdırılmış şekilde görebilmelisiniz!

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.

Komut dosyasını çalıştırırken, yeni mesaj yüklenmeden önce Updating the message... adımının biraz uzun sürdüğünü fark edebilirsiniz. Bunun sebebi madencilik sürecidir; işlemleri çıkarılırken takip etme konusunda meraklıysanız işlemin durumunu görüntülemek için Alchemy bellek havuzunu(opens in a new tab) ziyaret edebilirsiniz. İşlem düştüyse, Goerli Etherscan(opens in a new tab)'i kontrol etmek ve işlem karmanızı aramak da faydalı olur.

3. Bölüm: Akıllı Sözleşmenizi Etherscan'de yayımlayın

Akıllı sözleşmenizi hayata geçirmek için tüm zor işleri hallettiniz, şimdi bunu dünyayla paylaşma zamanı!

Akıllı sözleşmenizi Etherscan'de doğruladığınızda, herkes kaynak kodunuzu görebilir ve akıllı sözleşmenizle etkileşim kurabilir. Haydi başlayalım!

1. Adım: Etherscan hesabınızda bir API anahtarı oluşturun

Etherscan API anahtarı paylaşmaya çalıştığınız akıllı sözleşmenin sahibinin siz olduğunu onaylamak için gereklidir.

Eğer hala bir Etherscan hesabınız yoksa hesap oluşturmak için kaydolun(opens in a new tab).

Hesaba girdiğinizde, gezinti çubuğunda kullanıcı adınızı bulun, imleci üstüne getirin ve Profilim butonuna tıklayın.

Profil sayfanızda, bir yan gezinti çubuğu görmelisiniz. Yan gezinti çubuğundan API Anahtarları'nı seçin. Sonra, yeni bir API anahtarı oluşturmak için "Ekle" butonuna tıklayın, uygulamanıza hello-world adını verin ve Yeni API Anahtarı Oluştur butonuna tıklayın.

Yeni API anahtarınız API anahtar tablosunda görünüyor olmalıdır. API anahtarını panonuza kopyalayın.

Şimdi, .env dosyamıza Etherscan API anahtarını eklemeliyiz.

Ekledikten sonra, .env dosyanız şu şekilde görünmelidir:

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"

Hardhat dağıtılmış akıllı sözleşmeler

Hardhat-etherscan'i yükleme

Sözleşmenizi Hardhat kullanarak Etherscan'de yayımlamak basittir. Başlamak için öncelikle hardhat-etherscan eklentisini yüklemeniz gerekir. hardhat-etherscan, akıllı sözleşmenin kaynak kodunu ve ABI'sini Etherscan'de otomatik olarak doğrulayacaktır. Bunu eklemek için hello-world rehberinizde şunu çalıştırın:

1npm install --save-dev @nomiclabs/hardhat-etherscan

Yüklendiğinde, aşağıdaki ifadeyi hardhat.config.js'nizin en üstüne dahil edin ve Etherscan yapılandırma seçeneklerini ekleyin:

1// hardhat.config.js
2
3require("dotenv").config()
4require("@nomiclabs/hardhat-ethers")
5require("@nomiclabs/hardhat-etherscan")
6
7const { API_URL, PRIVATE_KEY, ETHERSCAN_API_KEY } = process.env
8
9module.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
21 // Obtain one at https://etherscan.io/
22 apiKey: ETHERSCAN_API_KEY,
23 },
24}
Tümünü göster

Akıllı Sözleşmenizi Etherscan üzerinden doğrulama

Tüm dosyaların kaydedildiğinden ve tüm değişkenlerin .env doğru şekilde yapılandırıldığından emin olun.

verify görevini çalıştırarak sözleşme adresinizi ve ağınızı dağıtıldığı konuma aktarın:

1npx hardhat verify --network goerli DEPLOYED_CONTRACT_ADDRESS 'Hello World!'

DEPLOYED_CONTRACT_ADDRESS adresinin Goerli test ağında dağıtılan akıllı sözleşmenizin adresi olduğundan emin olun. Ayrıca son bağımsız değişken olan ('Hello World!'), 1. Bölüm'de dağıtım aşamasında kullanılan dizi değeriyle aynı olmak zorundadır.

Eğer her şey yolunda gittiyse, terminalinizde aşağıdaki mesajı göreceksiniz:

1Successfully submitted source code for contract
2contracts/HelloWorld.sol:HelloWorld at 0xdeployed-contract-address
3for verification on Etherscan. Waiting for verification result...
4
5
6Successfully verified contract HelloWorld on Etherscan.
7https://goerli.etherscan.io/address/<contract-address>#contracts

Tebrikler! Akıllı sözleşmeniz artık Etherscan'de!

Akıllı sözleşmenize Etherscan'de göz atın!

Terminalinizde sağlanan bağlantıya gittiğinizde, akıllı sözleşme kodunuzun ve ABI'nizin Etherscan'de yayımlandığını göreceksiniz!

Bravo, başardınız! Artık herkes akıllı sözleşmenize yazabilir ya da onu çağırabilir! Bir dahaki sefere ne geliştireceğinizi görmek için sabırsızlanıyoruz!

4. Bölüm - Akıllı sözleşmenizi ön yüzle entegre etme

Bu öğreticinin sonuna geldiğinize, şunları nasıl yapacağınızı biliyor olacaksınız:

Bu merkeziyetsiz uygulama için ön yüz çerçevemiz olarak React(opens in a new tab)'i kullanacağız, fakat genel olarak projemize Web3 işlevselliğini getirmeye odaklanacağımız için temellerini açıklamaya çok vakit ayırmayacağımızı unutmayın.

Ön şart olarak, React'i yeni başlayan seviyesinde anlıyor olmanız gerekir. Eğer böyle değilse, Resmi React öğreticisini(opens in a new tab) bitirmenizi tavsiye ederiz.

Başlangıç ​​dosyalarını klonlayın

İlk olarak, bu projenin başlangıç dosyalarını almak ve bu kaynağı kendi yerel makinemize klonlamak için hello-world-part-four GitHub deposuna(opens in a new tab) gideceğiz.

Klonlanmış depoyu yerel olarak açın. İki klasöre sahip olduğunu göreceksiniz: starter-files ve completed.

  • starter-files- bu dizinde çalışacağız, kullanıcı arayüzünü Ethereum cüzdanınıza ve 3. Bölüm'de Etherscan'de yayımladığımız akıllı sözleşmeye bağlayacağız.
  • Bu completed, tamamlanmış olan öğreticiyi içerir ve sadece takıldığınızda yararlanacağınız bir kaynak olarak kullanılmalıdır.

Ardından, starter-files kopyanızı en sevdiğiniz kod düzenleyicide açın ve src klasörüne gidin.

Yazacağımız tüm kodlar src klasörünün altında yer alacaktır. Projemize Web3 işlevselliğini eklemek için HelloWorld.js bileşenini ve util/interact.js JavaScript dosyalarını düzenleyeceğiz.

Başlangıç dosyalarına göz atın

Kodlamaya başlamadan önce, başlangıç dosyalarında bize neler sağlandığını öğrenelim.

React projenizi çalıştırın

Tarayıcımızda React projesini çalıştırarak başlayalım. React'in güzelliği, projemizi tarayıcımızda çalıştırdıktan sonra, kaydettiğimiz tüm değişikliklerin tarayıcımızda canlı olarak güncellenmesidir.

Projeyi çalıştırmak için starter-files klasörünün kök dizinine gidip projenin bağımlılıklarını yüklemek için terminalinizde npm install'ı çalıştırın:

cd starter-files
npm install

Bunların kurulumu tamamlandıktan sonra terminalinizde npm start komutunu çalıştırın:

npm start

Bunu yaptığınızda, tarayıcınızda projemizin ön ucunu göreceğiniz http://localhost:3000/(opens in a new tab) adresi açılmalıdır. Bu, bir alandan (akıllı sözleşmenizde depolanan mesajı güncellemek için bir yer), bir "Connect Wallet" butonundan ve bir "Udate" butonundan oluşmalıdır.

Butonlardan birini tıklamayı denediğinizde çalışmadığını göreceksiniz, bunun sebebi hala işlevselliklerini programlamamız gerekmesidir.

HelloWorld.jsbileşeni

Düzenleyicimizdeki src klasörüne geri dönelim ve HelloWorld.js dosyasını açalım. Üzerinde çalışacağımız birincil React bileşeni olduğu için bu dosyadaki her şeyi anlamamız çok önemlidir.

Bu dosyanın en üstünde React kütüphanesini, useEffect ve useState kancalarını, ./util/interact.js'den bazı öğeleri (bunları yakında daha detaylı anlatacağız!) ve Alchemy logosunu içeren ve projemizi çalışır hale getirmemiz için gerekli olan birkaç önemli içe aktarım ifadeleri olduğunu fark edeceksiniz.

1// HelloWorld.js
2
3import React from "react"
4import { useEffect, useState } from "react"
5import {
6 helloWorldContract,
7 connectWallet,
8 updateMessage,
9 loadCurrentMessage,
10 getCurrentWalletConnected,
11} from "./util/interact.js"
12
13import alchemylogo from "./alchemylogo.svg"
Tümünü göster

Sırada, belirli olaylardan sonra güncelleyeceğimiz durum değişkenlerimiz var.

1// HelloWorld.js
2
3//State variables
4const [walletAddress, setWallet] = useState("")
5const [status, setStatus] = useState("")
6const [message, setMessage] = useState("No connection to the network.")
7const [newMessage, setNewMessage] = useState("")

Değişkenlerin her birinin temsil ettiği şeyler:

  • walletAddress - kullanıcının cüzdan adresini saklayan bir dize
  • status- kullanıcıya, merkeziyetsiz uygulama ile nasıl etkileşim kuracağı konusunda yardımcı olacak mesajlar içeren bir dizi
  • message - akıllı sözleşmedeki güncel mesajı depolayan bir dizi
  • newMessage - akıllı sözleşmeye yazılacak yeni mesajı depolayan bir dizi

Durum değişkenlerinden sonra, beş tane uygulanmamış fonksiyon göreceksiniz: useEffect ,addSmartContractListener, addWalletListener, connectWalletPressed ve onUpdatePressed. Bu fonksiyonların neler yaptığını aşağıda açıklayacağız:

1// HelloWorld.js
2
3//called only once
4useEffect(async () => {
5 //TODO: implement
6}, [])
7
8function addSmartContractListener() {
9 //TODO: implement
10}
11
12function addWalletListener() {
13 //TODO: implement
14}
15
16const connectWalletPressed = async () => {
17 //TODO: implement
18}
19
20const onUpdatePressed = async () => {
21 //TODO: implement
22}
Tümünü göster

Bu dosyanın sonuna doğru, bileşenimizin kullanıcı arayüzü bulunuyor.

1// HelloWorld.js
2
3//the UI of our component
4return (
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>
17
18 <h2 style={{ paddingTop: "50px" }}>Current Message:</h2>
19 <p>{message}</p>
20
21 <h2 style={{ paddingTop: "18px" }}>New Message:</h2>
22
23 <div>
24 <input
25 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>
31
32 <button id="publishButton" onClick={onUpdatePressed}>
33 Update
34 </button>
35 </div>
36 </div>
37)
Tümünü göster

Bu kodu dikkatli bir şekilde tararsanız, kullanıcı arayüzümüzde çeşitli durum değişkenleri kullandığımız yeri fark edeceksiniz:

Durum değişkenlerimize ek olarak publishButton ve walletButton butonları sırasıyla tıklandığında connectWalletPressed ve onUpdatePressed fonksiyonlarının çağrıldığını da göreceksiniz.

Son olarak, HelloWorld.js bileşeninin nereye eklendiğine değinelim.

React'teki diğer tüm bileşenler için bir kapsayıcı görevi gören ana bileşen olan App.js dosyasına giderseniz, HelloWorld.js bileşenimizin 7. satıra enjekte edildiğini görürsünüz.

Sonuncu ama diğerleriyle eşit öneme sahip olarak, size sağlanan bir dosyaya daha göz atalım: interact.js dosyası.

interact.jsdosyası

M-V-C(opens in a new tab) paradigmasını kurala bağlamak istediğimiz için merkeziyetsiz uygulamamızın mantığını, verilerini ve kurallarını yönetmek amacıyla fonksiyonlarımızı içeren ayrı bir dosya oluşturmak ve ardından bu fonksiyonları ön ucumuza (our HelloWorld.js component) aktarabilmek isteyeceğiz.

👆🏽Bu tam olarak interact.js dosyamızın amacı!

src dizininizde util klasörüne gittiğinizde bütün akıllı sözleşme etkileşimlerimizi, cüzdan işlevlerini ve değişkenleri içeren interact.js adında bir dosya eklemiş olduğumuzu göreceksiniz.

1// interact.js
2
3//export const helloWorldContract;
4
5export const loadCurrentMessage = async () => {}
6
7export const connectWallet = async () => {}
8
9const getCurrentWalletConnected = async () => {}
10
11export const updateMessage = async (message) => {}
Tümünü göster

Bu dosyanın en üstündeki helloWorldContract nesnesine yorum yazdığımızı fark edeceksiniz. Bu öğreticinin ilerleyen kısımlarında, nesnenin yorumkarını kaldıracak, akıllı sözleşmemimizi bu değişkenin içinde oluşturacak ve ardından HelloWorld.js bileşenimize aktaracağız.

helloWorldContract nesnemiz aşağıdakileri yaptıktan sonra dört uygulanmamış fonksiyon:

Ne üzerinde çalıştığımızı anladığımıza göre, akıllı sözleşmemizi nasıl okuyacağımızı öğrenelim!

3. Adım: Akıllı sözleşmenizden okuma

Akıllı sözleşmenizi okuyabilmek için aşağıdakileri başarıyla kurmanız gerekir:

  • Ethereum zincirine bir API bağlantısı
  • Akıllı sözleşmenizin yüklenmiş bir örneği
  • Akıllı sözleşme fonksiyonunuzu çağıran bir fonksiyon
  • Akıllı sözleşme değişikliklerinden okuduğunuz verilerin güncellemelerini takip eden bir dinleyici

Çok fazla adım varmış gibi görünebilir, fakat endişe etmeyin! Hepsini nasıl yapacağınızı adım adım göstereceğiz! :)

Ethereum zincirine bir API bağlantısı kurma

Bu öğreticinin 2. Bölümü'nde Alchemy Web3 anahtarını akıllı sözleşmemizi okuyabilmek için kullandığımızı hatırlıyor musunuz(opens in a new tab)? Zinciri okuyabilmek için de merkeziyetsiz uygulamanızda bir Alchemy Web3 anahtarına ihtiyacınız olacak.

Eğer sizde hala yoksa, ilk olarak kök dizininizin starter-files öğesinden Alchemy Web3(opens in a new tab)'e gidip yüklemek için aşağıdaki kodu terminalinizde çalıştırın:

1npm install @alch/alchemy-web3

Alchemy Web3(opens in a new tab), Web3.js(opens in a new tab) paketleyicisidir. Bir web3 geliştiricisi olarak hayatınızı kolaylaştıracak gelişmiş API yöntemleri ve diğer önemli avantajlar sağlar. Uygulamanızda hemen kullanmaya başlayabilmeniz için minimum yapılandırma gerektirecek şekilde tasarlanmıştır!

Ardından, API anahtarımızı aldıktan sonra depolayacağımız güvenli bir yerimiz olması için dotenv(opens in a new tab) paketini proje dizinimize yükleyin.

1npm install dotenv --save

Merkeziyetsiz uygulamamız için HTTP API anahtarımız yerine Websockets API anahtarımızı kullanıyor olacağız; bu, bizim akıllı sözleşmemizdeki mesajların değişip değişmediğini kontrol eden bir dinleyici kurmamızı sağlayacaktır.

API anahtarına sahip olduğunuzda, kök dizininizde bir .env dosyası oluşturun ve Alchemy Websockets url'nizi içine ekleyin. Sonrasında .env dosyanız şu şekilde görünmelidir:

1REACT_APP_ALCHEMY_KEY = wss://eth-goerli.ws.alchemyapi.io/v2/<key>

Artık Alchemy Web3 uç noktamızı merkeziyetsiz uygulamamıza kurmaya hazırız! util klasörümüzde yuvalanmış interact.js öğemize geri dönelim ve dosyanın başına aşağıdaki kodu ekleyelim:

1// interact.js
2
3require("dotenv").config()
4const alchemyKey = process.env.REACT_APP_ALCHEMY_KEY
5const { createAlchemyWeb3 } = require("@alch/alchemy-web3")
6const web3 = createAlchemyWeb3(alchemyKey)
7
8//export const helloWorldContract;

Yukarıda, ilk olarak Alchemy anahtarımızı .env dosyasından içe aktardık ve sonra da Alchemy Web3 uç noktamızı kurmak için alchemyKey'imizi createAlchemyWeb3'e gönderdik.

Bu uç nokta hazır olduğuna göre akıllı sözleşmemizi yükleme zamanı!

Merhaba Dünya akıllı sözleşmenizi yükleme

Merhaba Dünya akıllı sözleşmenizi yükleyebilmek için sözleşmenin adresine ve ABI'sine ihtiyacınız olacak. Bu öğreticinin 3. Bölümü'nü bitirdiyseniz bunların ikisini de Etherscan'de bulabilirsiniz.

Sözleşme ABI'nizi Etherscan'den alma

Bu öğreticinin 3. Bölüm'ünü atladıysanız, 0x6f3f635A9762B47954229Ea479b4541eAF402A6A(opens in a new tab) adresli Merhaba Dünya sözleşmesini kullanabilirsiniz. Sözleşmenin ABI'sini burada(opens in a new tab) bulabilirsiniz.

Bir sözleşmenin hangi fonksiyonu çağıracağını belirlemek ve fonksiyonun beklediğiniz biçimde veri döndürmesini sağlamak için bir sözleşme ABI'si gereklidir. Sözleşme ABI'mizi kopyaladıktan sonra onu src dizinindeki contract-abi.json adlı JSON dosyasına kaydedelim.

Contract-abi.json'unuz src klasöründe depolanmış olmalıdır.

Sözleşme adresimiz, ABI ve Alchemy Web3 uç noktamız hazır olduğuna göre, sözleşmemizin bir örneğini yüklemek için bu sözleşme yöntemini(opens in a new tab) kullanabiliriz. Sözleşme ABI'nizi interact.js dosyasının içine aktarın ve sözleşme adresinizi ekleyin.

1// interact.js
2
3const contractABI = require("../contract-abi.json")
4const contractAddress = "0x6f3f635A9762B47954229Ea479b4541eAF402A6A"

Sonunda helloWorldContract değişkenimizin yorumunu kaldırabilir ve AlchemyWeb3 uç noktasını kullanarak akıllı sözleşmemizi yükleyebiliriz:

1// interact.js
2export const helloWorldContract = new web3.eth.Contract(
3 contractABI,
4 contractAddress
5)

Hatırlatma olarak, interact.js kodunuzun ilk 12 satırı aşağıdaki gibi görünmelidir:

1// interact.js
2
3require("dotenv").config()
4const alchemyKey = process.env.REACT_APP_ALCHEMY_KEY
5const { createAlchemyWeb3 } = require("@alch/alchemy-web3")
6const web3 = createAlchemyWeb3(alchemyKey)
7
8const contractABI = require("../contract-abi.json")
9const contractAddress = "0x6f3f635A9762B47954229Ea479b4541eAF402A6A"
10
11export const helloWorldContract = new web3.eth.Contract(
12 contractABI,
13 contractAddress
14)
Tümünü göster

Sözleşmemizi yüklediğimize göre, artık loadCurrentMessage fonksiyonunu uygulayabiliriz!

interact.js dosyanıza loadCurrentMessage'ı uygulama

Bu fonksiyon aşırı basittir. Sözleşmemizi okumak için basit bir asenkronize web3 çağrısı yapacağız. Fonksiyonumuz akıllı sözleşmede depolanmış olan mesajı döndürecek:

interact.js dosyanızdaki loadCurrentMessage'ı aşağıdaki şekilde güncelleyin:

1// interact.js
2
3export const loadCurrentMessage = async () => {
4 const message = await helloWorldContract.methods.message().call()
5 return message
6}

Kullanıcı arayüzümüzde akıllı sözleşmeyi görüntülemek istediğimiz için HelloWorld.js bileşenimizdeki useEffect fonksiyonunu aşağıdaki şekilde güncelleyelim:

1// HelloWorld.js
2
3//called only once
4useEffect(async () => {
5 const message = await loadCurrentMessage()
6 setMessage(message)
7}, [])

Bileşenin ilk işlemesinde sadece loadCurrentMessage'ın çağrılmasını istediğimize dikkat edin. Yakında akıllı sözleşmedeki mesaj değiştiğinde kullanıcı arayüzünü otomatik olarak güncelleyen addSmartContractListener'ı uygulayacağız.

Dinleyicimize geçmeden önce, şu anda elimizde ne olduğuna bir bakalım! HelloWorld.js ve interact.js dosyalarınızı kaydedip http://localhost:3000/(opens in a new tab) öğesine gidin

Güncel mesajda artık "Ağ bağlantısı yok" yazmadığını göreceksiniz. Onun yerine, akıllı sözleşmede depolanmış olan mesajı yansıtır. İnanılmaz!

Kullanıcı arayüzünüz artık akıllı sözleşmede depolanan mesajı yansıtıyor olmalı

Dinleyiciye gelirsek...

addSmartContractListener'ı uygulayın

Bu öğretici serisinin 1. Bölümü'nde(opens in a new tab) yazdığımız HelloWorld.sol dosyasına dönerseniz, burada akıllı sözleşmemizin update fonksiyonunu çağırdıktan sonra meydana gelen UpdatedMessages adlı bir olay olduğunu hatırlayacaksınız (bkz. satır 9 ve 27):

1// HelloWorld.sol
2
3// Specifies the version of Solidity, using semantic versioning.
4// Learn more: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma
5pragma solidity ^0.7.3;
6
7// Defines a contract named `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
9contract HelloWorld {
10
11 //Emitted when update function is called
12 //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.
13 event UpdatedMessages(string oldStr, string newStr);
14
15 // Declares a state variable `message` of type `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.
17 string public message;
18
19 // Similar to many class-based object-oriented languages, a constructor is a special function that is only executed upon contract creation.
20 // Constructors are used to initialize the contract's data. Learn more:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors
21 constructor(string memory initMessage) {
22
23 // Accepts a string argument `initMessage` and sets the value into the contract's `message` storage variable).
24 message = initMessage;
25 }
26
27 // A public function that accepts a string argument and updates the `message` storage variable.
28 function update(string memory newMessage) public {
29 string memory oldMsg = message;
30 message = newMessage;
31 emit UpdatedMessages(oldMsg, newMessage);
32 }
33}
Tümünü göster

Akıllı sözleşme olayları sözleşmenizin, ön yüz uygulamanızın blokzinciri üzerinde bir olay olduğunda (yani bir olay gerçekleştiğinde) iletişim kurmasının bir yoludur. Bu yol, belli başlı olaylar için bir şeyleri dinlemek ve bu olaylar olduğunda aksiyon almak olabilir.

addSmartContractListener fonksiyonu spesifik olarak Merhaba Dünya akıllı sözleşmemizin UpdatedMessages olayını dinleyecek ve kullanıcı arayüzümüzü yeni mesajı gösterecek şekilde güncelleyecektir.

addSmartContractListener'ı aşağıdaki gibi değiştirin:

1// HelloWorld.js
2
3function 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}
Tümünü göster

Dinleyici bir olay algıladığında olacakları masaya yatıralım:

  • Olay yayımlandığında bir hata oluşursa, status durum değişkenimiz bu hatayı kullanıcı arayüzüne yansıtır.
  • Aksi takdirde döndürülen data nesnesini kullanacağız. data.returnValues dizinin ilk öğesinin önceki mesajı ve ikinci öğesinin güncellenmiş mesajı depoladığı sıfırdan başlatılan bir dizidir. Bütün olarak bakıldığında, başarılı bir olayda güncellenmiş mesajımıza message dizemizi kuracağız, newMessage dizesini sileceğiz ve status durum değişkenimizi akıllı sözleşmemizde yeni bir mesajın yayımlandığını yansıtacak şekilde güncelleyeceğiz.

Son olarak, useEffect fonksiyonumuzdaki dinleyicimizi çağırarak HelloWorld.js bileşenimizin ilk işlemesini başlatalım. Toparlarsak, useEffect fonksiyonunuz şu şekilde görünmelidir:

1// HelloWorld.js
2
3useEffect(async () => {
4 const message = await loadCurrentMessage()
5 setMessage(message)
6 addSmartContractListener()
7}, [])

Artık akıllı sözleşmemizi okuyabildiğimize göre, ona nasıl bir şeyler yazabileceğimizi öğrenmek de süper olur! Bununla birlikte, merkeziyetsiz uygulamamıza yazabilmek için önce ona bağlı bir Ethereum cüzdanı olmalıdır.

Yapacağımız bir sonraki şey ise Ethereum cüzdanımızı (MetaMask) kurmak ve merkeziyetsiz uygulamamıza bağlamaktır!

4. Adım: Ethereum cüzdanınızı kurun

Kullanıcılar, Ethereum zincirine herhangi bir şey yazabilmek için sanal cüzdanlarının özel anahtarlarını kullanarak işlemler imzalamalıdır. Bu öğreticide, Ethereum hesap adresinizi yönetmeniz için tarayıcıda bulunan bir sanal cüzdan olan ve son kullanıcı için işlem imzalamayı çok basit bir hale getiren MetaMask(opens in a new tab)'ı kullanacağız.

Ethereum'daki işlemlerin nasıl çalıştığı hakkında daha fazla bilgi edinmek istiyorsanız, Ethereum Vakfı'nın bu sayfasına göz atın.

MetaMask'i indirin

Buradan(opens in a new tab) ücretsiz olarak bir MetaMask hesabı indirebilir ve oluşturabilirsiniz. Bir hesap oluştururken ya da zaten bir hesabınız varsa, sağ üstten "Goerli Test Ağına" geçin (bu sayede gerçek parayla denemeler yapmayız).

Bir Musluktan ether ekleyin

Ethereum blokzincirinde bir işlem imzalamak için biraz sahte Eth'ye ihtiyacımız olacak. Eth almak için FaucETH(opens in a new tab)'e gidip Goerli hesap adresinizi girebilir, "Fon iste" öğesine tıklayıp açılır menüden "Ethereum Test Ağı Goerli" seçimi yapabilir ve son olarak tekrar "Fon iste" düğmesine tıklayabilirsiniz. Kısa bir süre sonra MetaMask hesabınızda Eth'i görmelisiniz!

Bakiyenizi kontrol etme

Bakiyemizin yerinde olduğundan emin olmak için Alchemy'nin düzenleyici aracını(opens in a new tab) kullanarak bir eth_getBalance(opens in a new tab) isteği oluşturalım. Bu, cüzdanımızdaki Eth miktarını döndürür. MetaMask hesap adresinizi girdikten ve "Send Request"e tıkladıktan sonra aşağıdaki gibi bir yanıt görmelisiniz:

1{"jsonrpc": "2.0", "id": 0, "result": "0xde0b6b3a7640000"}

NOT: Bu sonuç eth değil wei hâlindedir. Wei, ether'ın en küçük birimi olarak kullanılır. Wei'den eth'e dönüşüm: 1 eth = 10¹⁸ wei. Yani 0xde0b6b3a7640000'ı ondalık sayıya dönüştürürsek 1*10¹⁸ elde ederiz, bu da 1 eth'e eşittir.

Vay be! Tüm sahte paramız yerli yerinde! 🤑

5. Adım: MetaMask'ı kullanıcı arayüzünüze bağlayın

Artık MetaMask cüzdanımız kurulduğuna göre, merkeziyetsiz uygulamamızı ona bağlayalım!

connectWalletfonksiyonu

interact.js dosyamızda connectWallet fonksiyonunu uygulayalım, bu fonksiyonu sonrasında HelloWorld.js bileşenimizde çağırabiliriz.

connectWallet'u aşağıdaki gibi değiştirelim:

1// interact.js
2
3export 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 obj
14 } 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.html`}>
28 You must install MetaMask, a virtual Ethereum wallet, in your
29 browser.
30 </a>
31 </p>
32 </span>
33 ),
34 }
35 }
36}
Tümünü göster

Bu dev kod bloğu tam olarak ne yapar?

İlk olarak, tarayıcınızda window.ethereum'un etkinleştirilmiş olup olmadığını kontrol eder.

window.ethereum, MetaMask ve diğer cüzdan sağlayıcıları tarafından enjekte edilen ve web sitelerinin kullanıcıların Ethereum hesaplarını talep etmesine izin veren küresel bir API'dir. Onaylandıysa, kullanıcının bağlı olduğu blokzincirlerden veri okuyabilir ve kullanıcıya mesajlar ve işlemler imzalamasını önerebilir. Daha fazla bilgi için MetaMask belgelerine(opens in a new tab) göz atın!

window.ethereum yoksa, MetaMask kurulu değil demektir. Bu, bir JSON nesnesinin döndürülmesiyle sonuçlanır; burada döndürülen address boş bir dizedir ve status JSX nesnesi, kullanıcının MetaMask'i yüklemesi gerektiğini bildirir.

Şimdi, eğer window.ethereum varsa, işte o zaman işler ilginçleşiyor.

Bir deneme/yakalama döngüsü ile window.ethereum.request({ method: "eth_requestAccounts" });(opens in a new tab) çağrısı yaparak MetaMask'a bağlanmaya çalışacağız. Bu fonksiyonun çağrılması, tarayıcıda MetaMask'i açar ve bu sayede kullanıcıdan cüzdanını merkeziyetsiz uygulamanıza bağlaması istenir.

  • Kullanıcı bağlanmayı seçerse, method: "eth_requestAccounts", kullanıcının merkeziyetsiz uygulamaya bağlı tüm hesap adreslerini içeren bir dizi döndürür. Toplamda, connectWallet fonksiyonumuz bu dizideki ilk address'i içeren bir JSON nesnesi (9. satıra bakın) ve kullanıcıdan akıllı sözleşmeye bir mesaj yazmasını isteyen bir status mesajı döndürür.
  • Kullanıcı bağlantıyı reddederse, JSON nesnesi, döndürülen address için boş bir dize ve kullanıcının bağlantıyı reddettiğini yansıtan bir status mesajı içerir.

Artık bu connectWallet'ı yazdığımıza göre, sonraki adım onu HelloWorld.js bileşenimize çağırmaktır.

HelloWorld.js Kullanıcı Arayüzü Bileşenimize connectWalletfonksiyonunu ekleyelim

HelloWorld.js içinde bulunan connectWalletPressed'a gidin ve aşağıdaki gibi güncelleyin:

1// HelloWorld.js
2
3const connectWalletPressed = async () => {
4 const walletResponse = await connectWallet()
5 setStatus(walletResponse.status)
6 setWallet(walletResponse.address)
7}

İşlevselliğimizin çoğunun interact.js dosyasındaki HelloWorld.js'den nasıl da soyutlandığını görebiliyor musunuz? Bu, M-V-C paradigmasına uymamız içindir!

connectWalletPressed'de, içe aktarılan connectWallet fonksiyonumuza bir bekleme çağrısı yaparız ve yanıtını kullanarak durum kancaları aracılığıyla status ve walletAddress değişkenlerimizi güncelleriz.

Şimdi, iki dosyayı da (HelloWorld.js and interact.js) kaydedelim ve şu ana kadarki kullanıcı arayüzümüzü test edelim.

http://localhost:3000/(opens in a new tab) sayfasında tarayıcınızı açın ve sayfanın sağ üst tarafında bulunan "Connect Wallet" butonuna tıklayın.

MetaMask yüklüyse, cüzdanınızı merkeziyetsiz uygulamanıza bağlamanız istenecektir. Bağlanmak için daveti kabul edin.

Cüzdan butonunuzun, adresinizin artık bağlı olduğunu gösterdiğini görmeniz beklenir! Eveeet 🔥

Ardından, sayfayı yenilemeyi deneyin... Garip. Cüzdan düğmemiz zaten bağlı olmasına rağmen MetaMask'i bağlamamızı istiyor...

Yine de korkmanıza gerek yok! Bunu, getCurrentWalletConnected'ı uygulayarak kolaylıkla adresleyebiliriz (anladınız mı)?; bu da merkeziyetsiz uygulamamıza bir adresin bağlı olup olmadığını kontrol edecek ve buna göre kullanıcı arayüzümüzü güncelleyecektir!

getCurrentWalletConnectedfonksiyonu

interact.js dosyasındaki getCurrentWalletConnected fonksiyonunuzu aşağıdaki gibi güncelleyin:

1// interact.js
2
3export 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.html`}>
34 You must install MetaMask, a virtual Ethereum wallet, in your
35 browser.
36 </a>
37 </p>
38 </span>
39 ),
40 }
41 }
42}
Tümünü göster

Bu kod, önceki adımda yazdığımız connectWallet fonksiyonuna çok benzer.

Temel fark, kullanıcının cüzdanını bağlaması için MetaMask'i açan eth_requestAccounts yöntemini çağırmak yerine, burada yalnızca şu anda merkeziyetsiz uygulamamıza bağlı olan MetaMask adreslerini içeren bir dizi döndüren eth_accounts yöntemini çağırmamızdır.

Bu fonksiyonu çalışırken görmek için onu HelloWorld.js bileşenimizin useEffect fonksiyonuyla çağıralım:

1// HelloWorld.js
2
3useEffect(async () => {
4 const message = await loadCurrentMessage()
5 setMessage(message)
6 addSmartContractListener()
7
8 const { address, status } = await getCurrentWalletConnected()
9 setWallet(address)
10 setStatus(status)
11}, [])
Tümünü göster

Dikkat edin, walletAddress ve status durum değişkenlerimizi güncellemek için getCurrentWalletConnected çağrımızın yanıtını kullanıyoruz.

Artık bu kodu eklediğinize göre, sayfayı yenilemeyi deneyin.

Güzeeeeeel! Düğme, bağlı olduğunuzu söylemeli ve yeniledikten sonra bile bağlı cüzdanınızın adresinin bir önizlemesini göstermelidir!

addWalletListener'ı uygulayın

Merkeziyetsiz uygulama cüzdanı kurulumumuzun son adımı, örneğin kullanıcı bağlantısını keserek veya hesap değiştirerek cüzdanımızın durumunu değiştirdiğinde kullanıcı arayüzümüzün güncellenmesi için cüzdan dinleyicisini uygulamaktır.

HelloWorld.js dosyanızda addWalletListener fonksiyonunu aşağıdaki gibi değiştirin:

1// HelloWorld.js
2
3function 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.html`}>
19 You must install MetaMask, a virtual Ethereum wallet, in your browser.
20 </a>
21 </p>
22 )
23 }
24}
Tümünü göster

Bu noktada ne olup bittiğini anlamak için bizim yardımımıza ihtiyacınız olmadığına bahse girebilirim, fakat hiçbir ayrıntıyı atlamamak adına hızlıca anlatalım:

  • İlk olarak, fonksiyonumuz window.ethereum'un etkin olup olmadığını kontrol eder (yani MetaMask kurulu olup olmadığını).
    • Değilse, status durum değişkenimizi, kullanıcının MetaMask'i yüklemesini isteyen bir JSX dizesine ayarlamamız yeterlidir.
    • Etkinleştirilirse, 3. satırda window.ethereum.on("accountsChanged") dinleyicisini kurarız ve bu dinleyici MetaMask cüzdanındaki, kullanıcının merkeziyetsiz uygulamaya ek bir hesap bağladığı, hesapları değiştirdiği veya bir hesabın bağlantısını kestiği anları da içeren durum değişikliklerini dinler. Bağlı en az bir hesap varsa, walletAddress durum değişkeni, dinleyici tarafından döndürülen accounts dizisindeki ilk hesap olarak güncellenir. Aksi takdirde, walletAddress boş bir dize olarak ayarlanır.

Son ama bir o kadar da önemli olarak, bunu useEffect fonksiyonumuzda çağırmalıyız:

1// HelloWorld.js
2
3useEffect(async () => {
4 const message = await loadCurrentMessage()
5 setMessage(message)
6 addSmartContractListener()
7
8 const { address, status } = await getCurrentWalletConnected()
9 setWallet(address)
10 setStatus(status)
11
12 addWalletListener()
13}, [])
Tümünü göster

İşte bu kadar! Cüzdan fonksiyonlarımızın tümünün programlanmasını başarıyla tamamladık! Şimdi sıra son görevimizde: akıllı sözleşmemizde depolanan mesajı güncellemek!

6. Adım: updateMessagefonksiyonunu uygulama

Evet dostum, evimizdeki rahatlığa ulaştık! interact.js dosyanızın updateMessage kısmında şunları yapacağız:

  1. Yayımlayamak istediğimiz mesajın geçerli olduğundan emin olmak
  2. MetaMask kullanarak işlemimizi imzalamak
  3. HelloWorld.js ön yüz bileşenimizden bu fonksiyonu çağırmak

Bu, fazla zaman almayacak; hadi bu merkeziyetsiz uygulamayı bitirelim!

Girdi hatası işleme

Doğal olarak, fonksiyonun başında bir çeşit girdi hatasını işlemek mantıklı olur.

Yüklü bir MetaMask uzantısı veya bağlı bir cüzdan yoksa (yani aktarılan address boş bir dizeyse) ya da message boş bir dizeyse fonksiyonumuzun erken dönüş yapmasını isteriz. Hadi updateMessage'a aşağıdaki hata işlemeleri ekleyelim:

1// interact.js
2
3export 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 }
10
11 if (message.trim() === "") {
12 return {
13 status: "❌ Your message cannot be an empty string.",
14 }
15 }
16}
Tümünü göster

Artık düzgün bir girdi hatası işleme sistemimiz olduğuna göre, işlemi MetaMask üzerinden imzalama zamanı geldi demektir!

İşlemimizi imzalama

Geleneksel web3 Ethereum işlemleri ile haşır neşirseniz, az sonra yazacağımız kod tanıdık gelecektir. Girdi hatası işleme kodunuzun altında updateMessage'a şunları ekleyin:

1// interact.js
2
3//set up transaction parameters
4const transactionParameters = {
5 to: contractAddress, // Required except during contract publications.
6 from: address, // must match user's active address.
7 data: helloWorldContract.methods.update(message).encodeABI(),
8}
9
10//sign the transaction
11try {
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 be
25 updated automatically.
26 </span>
27 ),
28 }
29} catch (error) {
30 return {
31 status: "😥 " + error.message,
32 }
33}
Tümünü göster

Olan biteni açıklayalım. Önce, işlem parametrelerimizi oluşturuyoruz; burada:

  • to alıcı adresini belirtir (akıllı sözleşmemiz)
  • from, fonksiyonumuza aktardığımız address değişkeni olan işlemin imzalayıcısını belirtir
  • data ise Merhaba Dünya akıllı sözleşmesinin update yöntemlerine yönelik çağrıları içerir ve message dizesi değişkenlerini girdi olarak alır

Ardından, MetaMask'ten işlemi imzalamasını istediğimiz bir window.ethereum.request bekleme çağrısı yaparız. 11. ve 12. satırlarda eth yöntemimizi, eth_sendTransaction, belirttiğimizi ve transactionParameters'ımıza aktardığımızı gözdn kaçırmayın.

Bu noktada, MetaMask tarayıcıda açılır ve kullanıcıdan işlemi imzalamasını veya reddetmesini ister.

  • İşlem başarılı olursa fonksiyon, status JSX dizesinin kullanıcıya Etherscan'den işlem hakkında daha fazla bilgi edinmesini anımsattığı bir JSON nesnesi döndürür.
  • İşlem başarısız olursa fonksiyon, status dizesinin hata mesajını aktardığı bir JSON öğesi döndürür.

Toparlarsak, updateMessage fonksiyonumuz şu şekilde görünmelidir:

1// interact.js
2
3export const updateMessage = async (address, message) => {
4 //input error handling
5 if (!window.ethereum || address === null) {
6 return {
7 status:
8 "💡 Connect your MetaMask wallet to update the message on the blockchain.",
9 }
10 }
11
12 if (message.trim() === "") {
13 return {
14 status: "❌ Your message cannot be an empty string.",
15 }
16 }
17
18 //set up transaction parameters
19 const transactionParameters = {
20 to: contractAddress, // Required except during contract publications.
21 from: address, // must match user's active address.
22 data: helloWorldContract.methods.update(message).encodeABI(),
23 }
24
25 //sign the transaction
26 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 will
40 be updated automatically.
41 </span>
42 ),
43 }
44 } catch (error) {
45 return {
46 status: "😥 " + error.message,
47 }
48 }
49}
Tümünü göster

Son ama bir o kadar da önemli olarak, updateMessage fonksiyonumuzu HelloWorld.js bileşenimize bağlamalıyız.

updateMessageHelloWorld.jsön yüzüne bağlama

onUpdatePressed fonksiyonumuz içeri aktarılan updateMessage fonksiyonuna bir bekleme çağrısı yapmalı ve status durum değişkenini işlemimizin başarılı ya da başarısız olduğunu yansıtacak şekilde güncellemelidir:

1// HelloWorld.js
2
3const onUpdatePressed = async () => {
4 const { status } = await updateMessage(walletAddress, newMessage)
5 setStatus(status)
6}

Bu çok açık ve basit. Bilin bakalım ne oldu? MERKEZİYETSİZ UYGULAMANIZ TAMAMLANDI!!!

Devam edin ve Güncelle butonunu test edin!

Kişiye özel merkeziyetsiz uygulamanızı üretin

Tebrikler, öğreticinin sonuna geldiniz! Hatırlatma olarak, burada şunları nasıl yapacağınızı öğrendiniz:

Artık bu öğreticide size verilmiş olan bu becerileri kullanarak kendi kişisel merkeziyetsiz uygulama projenizi yapabilirsiniz! Her zamanki gibi, herhangi bir sorunuz varsa yardım istemek için bize Alchemy Discord(opens in a new tab) aracılığıyla ulaşmaktan çekinmeyin. 🧙‍♂️

Bu öğreticiyi bitirdiğinize, yaşadığınız deneyimi ya da yorumlarınızı Twitter'dan @alchemyplatform(opens in a new tab) bizi etiketleyerek aktarabilirsiniz!

Son düzenleme: @wackerow(opens in a new tab), 7 Mayıs 2024

Bu rehber yararlı oldu mu?