WEB3DEV

Cover image for Introdução a Web3.js - Crash Course Desenvolvedor Ethereum Blockchain
Lorenzo Battistela
Lorenzo Battistela

Posted on

Introdução a Web3.js - Crash Course Desenvolvedor Ethereum Blockchain

Este artigo foi escrito por Gregory McCubbin e publicado na Dapp University. Traduzido por Lorenzo Battistela.

Por Gregory McCubbin - 20 de Junho de 2022

Olá para todos, é o Gregory da Dapp University!

Hoje eu vou ensinar você como começar a usar a biblioteca Web3.js, a principal biblioteca em JavaScript para interagir com a Blockchain Ethereum. Vou te mostrar o que Web3.js é e como usamos para falar com a blockchain Ethereum nesse tutorial com 8 partes.

https://youtu.be/t3wM5903ty0

# 1 - O que é Web3.js

O vídeo acima é o primeiro nesse tutorial de 8 partes. Nessa aula, vou dar uma explicação geral da biblioteca Web3.js, e então vou mostrar a você como checar o saldo de uma conta Ethereum.

Existem alguns diferentes aspectos no que tange o desenvolvimento de aplicações com o Ethereum:

  1. Desenvolvimento de smart contract - escrever código que é implantado na blockchain com a linguagem de programação Solidity.
  2. Desenvolver websites ou clientes que interagem com a blockchain - escrever código que lê e escreve dados na blockchain com os smart contracts.

Web3.js permite que você complete a segunda responsabilidade: desenvolver clientes que interagem com a blockchain Ethereum. É uma coleção de bibliotecas que permite que você execute ações como mandar Ether de uma conta para outra, ler e escrever dados a partir de smart contracts, criar smart contracts e muito mais!

Se você tiver um background em desenvolvimento web, você deve ter usado jQuery para fazer o Ajax chamar um servidor web. Esse é um bom ponto de partida para entender a função do Web3.js. Ao invés de usar um jQuery para ler e escrever dados em um web server, você pode usar o Web3.js para ler e escrever na blockchain Ethereum.

Deixe-me explicar como você pode usar Web3.js para falar com a blockchain Ethereum. Aqui está o diagrama de como um cliente fala com o Ethereum:

Image description

Web3.js fala com a blockchain Ethereum com o JSON RPC, que significa protocolo "Remote Procedure Call", ou protocolo de chamada de procedimento remoto. O Ethereum é uma rede ponto a ponto de nós e armazena uma cópia de todos os dados e código na blockchain. Web3.js nos permite fazer requisições para um nó individual do Ethereum com JSON RPC para ler e escrever dados na rede. É quase como usar jQuery com uma API JSON para ler e escrever dados com um servidor web.

Dependências

Existem algumas dependências que vão ajudar você a começar a desenvolver com Web3.js

Node Package Manager (NPM)

A primeira dependência que precisamos é o Node Package Manager, ou NPM, que vem junto com o Node.js. Você pode ver se você já tem o node instalado na sua máquina abrindo o terminal e digitando:

$ node -v
Enter fullscreen mode Exit fullscreen mode

Biblioteca Web3.js

Você pode instalar a biblioteca Web3.js com o NPM no seu terminal dessa maneira:

$ npm install web3
Enter fullscreen mode Exit fullscreen mode

Infura RPC URL

Para conectar com o nó Ethereum usando JSON RPC na rede principal, precisamos de acesso ao nó Ethereum. Existem algumas maneiras de fazer isso. Por exemplo, você poderia rodar seu próprio nó com Geth ou Parity. Mas isso requer que você baixe muitos dados da blockchain e mantenha esses dados sincronizados. Isso é uma dor de cabeça.

Por conveniência, podemos usar Infura para acessar um nó Ethereum sem rodar um nó você mesmo. Infura é um serviço que providencia um nó remoto do Ethereum de graça. Tudo que você precisa fazer é se inscrever e obter uma chave de API e o RPC URL da rede que você quer se conectar.

Uma vez que você tiver se inscrito, seu RPC URL da Infura deve se parecer com isso:

https://mainnet.infura.io/YOUR_INFURA_API_KEY

Checando o saldo das contas

Agora que todas as suas dependências estão instaladas, você pode começar a desenvolver com o Web3.js! Primeiro, você deve inicializar o console Node no seu terminal, desse jeito:

$ node
Enter fullscreen mode Exit fullscreen mode

Agora você tem o console do Node aberto! Dentro do console Node, você pode importar o Web3.js dessa maneira:

const Web3 = require('web3')
Enter fullscreen mode Exit fullscreen mode

Agora você tem acesso a uma variável onde você pode criar uma nova conexão! Antes de gerarmos uma conexão Web3, precisamos atribuir o URL da Infura para uma variável, dessa maneira:

const rpcURL = "https://mainnet.infura.io/YOUR_INFURA_API_KEY"
Enter fullscreen mode Exit fullscreen mode

Esteja certo de que você substitua YOUR_INFURA_API_KEY pela sua chave real da API da Infura, que você conseguiu anteriormente. Agora você pode instanciar uma conexão Web3 como essa:

const web3 = new Web3(rpcURL)
Enter fullscreen mode Exit fullscreen mode

Agora você tem uma conexão real com a Web3 que vai permitir que você fale com a rede principal da Ethereum! Vamos usar essa conexão para checar o saldo desta conta:

0x90e63c3d53e0ea496845b7a03ec7548b70014a91 . Podemos ver quanto Ether essa conta tem checando seu saldo com web3.eth.getBalance().

Primeiro, vamos atribuir o endereço para uma variável:

const account = "0x90e63c3d53E0Ea496845b7a03ec7548B70014A91"
Enter fullscreen mode Exit fullscreen mode

Agora, vamos checar o saldo da conta como isso:

web3.eth.getBalance(address, (err, wei) => {
  balance = web3.utils.fromWei(wei, 'ether')
})
Enter fullscreen mode Exit fullscreen mode

Deixe-me explicar esse código. Primeiro, vamos checar o saldo chamando web3.eth.getBalance(), que aceita uma função callback com dois argumentos, um erro e o saldo. Vamos ignorar o argumento do erro por agora, e referenciar o saldo com o argumento wei. A Ethereum expressa os saldos em Wei, que é a menor subdivisão do Ether, como uma parte de centavo. Podemos converter esse saldo para Ether com web3.utils.fromWei(wei, "ether").

E é isso! Essa é a conclusão da primeira parte deste tutorial. Agora que você já viu o que é a biblioteca Web3.js e você pode começar a usá-la para checar saldos de Ethereum de contas. Aqui está um resumo do código que escrevemos nesse tutorial:

const Web3 = require('web3')
const rpcURL = '' // Your RPC URL goes here
const web3 = new Web3(rpcURL)
const address = '' // Your account address goes here
web3.eth.getBalance(address, (err, wei) => {
  balance = web3.utils.fromWei(wei, 'ether')
})
Enter fullscreen mode Exit fullscreen mode

Você também pode baixar todos os códigos de exemplo dessa série de tutoriais pelo github.

Também vou mencionar que ler a documentação do Web3.js dará a você uma visão geral do que você pode fazer com a biblioteca. Eu recomendo fortemente que você dê uma olhada na documentação, mesmo que você não entenda todos os aspectos de suas funcionalidades. Você pode deixar a documentação completa para o Web3.js aqui:

https://web3js.readthedocs.io/en/1.0/

Adicionalmente, note que Web3.js está sendo desenvolvido constantemente. Se você visitar o repositório no github do Web3.js para seguir seu progresso, você também pode ler o código para ganhar um melhor entendimento sobre a biblioteca. Você pode encontrar o repositório no github aqui:

https://github.com/ethereum/web3.js/

#2 Leia dados de Smart Contracts com Web3.js

Esse é o segundo vídeo da série de tutoriais. Nesse vídeo, vou mostrar como ler dados de smart contracts da blockchain Ethereum.

https://youtu.be/tu92jcqdn6s

Para podermos ler dados de smart contracts com Web3.js, precisamos de duas coisas:

  1. Uma representação do smart contract que queremos interagir em Javascript.
  2. Uma maneira de chamar as funções do smart contract quando estivermos lendo os dados.

Podemos ter uma representação Javascript de um smart contract Ethereum com a função web3.eth.Contract() . Essa função espera dois argumentos: um para o ABI do smart contract e um para o endereço do smart contract.

Um ABI de smart contract significa "Abstract Binary Interface" (Interface Binária Abstrata), e é uma array de JSON que descreve como um smart contract específico funciona. Aqui está um exemplo de ABI:

const abi = [{"constant":true,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_releaseTime","type":"uint256"}],"name":"mintTimelocked","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[],"name":"MintFinished","type":"event"},{"anonymous":false,"inputs":[],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]
Enter fullscreen mode Exit fullscreen mode

Essa é uma array longa e parece ser inquebrável, eu sei! Não se preocupe se isso parecer demais. :) Esse exemplo é o ABI para o token OmiseGo, que implementa o padrão de token ERC-20 (se você não estiver familiarizado com esse padrão, você pode assistir esse vídeo). Você pode encontrar mais detalhes sobre esse token, incluindo seu ABI e endereço no Etherscan. Nós vamos usar o ABI desse _smart contract_vpara o resto do exemplo.

Enquanto estamos aqui, vou em frente e armazenar o endereço do token OMG da rede principal da Ethereum:

const address = "0xd26114cd6EE289AccF82350c8d8487fedB8A0C07"
Enter fullscreen mode Exit fullscreen mode

Agora que temos ambos os valores atribuídos, podemos criar uma representação completa do smart contract do token OMG dessa maneira:

const contract = new web3.eth.Contract(abi, address)
Enter fullscreen mode Exit fullscreen mode

Agora que essa primeira parte da lição está completa, precisamos completar a segunda parte: ler dados do smart contract chamando suas funções. Todas as funções do smart contract estão listadas no contract.methods dentro do contrato que atribuímos. Por exemplo, podemos chamar contract.methods.myFunction() se o contrato implementar myFunction().

Ótimo! Então podemos teoricamente chamar qualquer função que o smart contract implementa. Mas como nós saberemos quais funções ele implementa? Poderíamos logar contract.methods no console, e ver o que é retornado (você pode me assistir fazendo isso no vídeo acima). Entretanto, visto que o smart contract implementou o padrão ERC20, nós sabemos que ele implementa algumas funções como totalSupply(), name(), symbol() e balanceOf(). Podemos ler cada um desses valores individualmente, como isso:

Primeiro, o supply total de todos os tokens OMG em existência:

contract.methods.totalSupply().call((err, result) => { console.log(result) })
// > 140245398
Enter fullscreen mode Exit fullscreen mode

Segundo, o nome do token OMG:

contract.methods.name().call((err, result) => { console.log(result) })
// > OMG Token
Enter fullscreen mode Exit fullscreen mode

Terceiro, o symbolo do token OMG:

contract.methods.name().call((err, result) => { console.log(result) })
// > OMG Token
Enter fullscreen mode Exit fullscreen mode

Por último, podemos checar o saldo de uma conta específica. Eu procurei alguém que tivesse muitos tokens OMG no Etherscan, e encontrei este endereço 0xd26114cd6EE289AccF82350c8d8487fedB8A0C07 . Podemos checar o saldo dessa conta assim:

contract.methods.balanceOf('0xd26114cd6EE289AccF82350c8d8487fedB8A0C07').call((err, result) => { console.log(result) })
// > A very large number...
Enter fullscreen mode Exit fullscreen mode

E é isso! É fácil assim ler dados de smart contracts com o Web3.js. Aqui está um resumo de todo o nosso código dessa missão:

const Web3 = require('web3')
const rpcURL = '' // Your RCP URL goes here
const web3 = new Web3(rpcURL)

const abi = [{"constant":true,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_releaseTime","type":"uint256"}],"name":"mintTimelocked","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[],"name":"MintFinished","type":"event"},{"anonymous":false,"inputs":[],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]
Enter fullscreen mode Exit fullscreen mode

Você também pode fazer o download dos códigos de exemplo desse tutorial de séries no github.

# 3 - Dentro das transações Ethereum

Esse é o terceiro vídeo dessa série de tutoriais. Esse vídeo vai mostrar como criar transações na Blockchain Ethereum com o Web3.js. Essa aula vai desde iniciante até levemente avançada. Vou mostrar o que acontece quando uma transação Ethereum é criada, e mostrarei como enviar uma transação manualmente para a rede com o Web3.js

https://youtu.be/uFdjZ-B3GCM

Além de aprender Web3.js, o propósito dessa aula é ajudar você a entender os fundamentos de como as transações funcionam na Blockchain Ethereum. Quando você cria uma transação, você está escrevendo dados para a Blockchain e atualizando o seu estado. Existem várias maneiras de fazer isso, como mandar Ether de uma conta para outra, chamar uma função de um smart contract que escreva dados, e fazer o deploy de um smart contract na Blockchain. Podemos obter um entendimento maior desses conceitos performando essas ações com a biblioteca Web3.js e observando como cada passo acontece.

Para enviar transações para a rede, precisaremos assiná-las primeiro. Vou utilizar uma biblioteca Javascript adicional para fazer isso, chamada ethereumjs-tx. Você pode instalar essa dependência na linha de comando, desse jeito:

$ npm install ethereumjs-tx
Enter fullscreen mode Exit fullscreen mode

A razão de utilizarmos essa biblioteca é que queremos assinar todas as transações localmente. Se estivéssemos rodando nosso próprio nó Ethereum localmente, poderíamos desbloquear uma conta armazenada localmente e assinar todas as transações localmente. Se esse fosse o caso, não precisaríamos necessariamente utilizar essa biblioteca. Entretanto, estamos usando um nó remoto hospedado pelo Infura nesse tutorial. Enquanto o Infura é um serviço confiável, ainda queremos assinar as transações localmente ao invés de deixar o nó remoto gerenciar nossas chaves.

Isso é exatamente o que vamos fazer nessa aula. Vou mostrar como criar uma transação crua, assiná-la, mandar a transação e espalhá-la para a rede! Para fazer isso, preciso criar um arquivo simples app.js para executar o código dessa missão, ao invés de fazer tudo no console.

Dentro do arquivo app.js, primeiro vamos importar a biblioteca que instalamos, dessa maneira:

var Tx = require('ethereumjs-tx')
Enter fullscreen mode Exit fullscreen mode

Agora, vamos configurar uma conexão Web3 como fizemos nas aulas anteriores:

const Web3 = require('web3')
const web3 = new Web3('https://ropsten.infura.io/YOUR_INFURA_API_KEY')
Enter fullscreen mode Exit fullscreen mode

Note que estamos utilizando a rede de testes Ropsten, que é diferente da main net Ethereum que usamos na aula anterior. Queremos usar uma rede de testes, pois todas as transações custam gas em forma de Ether. Podemos usar Ether falso na rede de testes Ropsten sem ter a preocupação de gastar dinheiro. Você pode obter Ether falso em uma faucet da rede de teste Ropsten. Aqui estão duas faucets que você pode utilizar:

http://faucet.ropsten.be:3001/

https://faucet.metamask.io/

Nessa missão, criaremos uma transação que envia Ether falso de uma conta para outra. Para fazer isso, precisaremos de duas contas e suas chaves privadas. Você pode criar contas com o Web3.js dessa maneira:

web3.eth.accounts.create()
// > {
//    address: "0xb8CE9ab6943e0eCED004cDe8e3bBed6568B2Fa01",
//    privateKey: "0x348ce564d427a3311b6536bbcff9390d69395b06ed6c486954e971d960fe8709",
//    signTransaction: function(tx){...},
//    sign: function(data){...},
//    encrypt: function(password){...}
// }
Enter fullscreen mode Exit fullscreen mode

Uma vez que você tiver criado as duas contas, lembre-se de enviar um pouco de Ether falso para elas a partir de uma faucet. Agora, vamos atribuí-las para variáveis do nosso script, dessa maneira:

const account1 = '0xb8CE9ab6943e0eCED004cDe8e3bBed6568B2Fa01'
const account2 = '0xb8CE9ab6943e0eCED004cDe8e3bBed6568B2Fa02'
Enter fullscreen mode Exit fullscreen mode

Lembre-se de usar as contas que você gerou, visto que essas contas não funcionarão para você nessa aula. Vamos salvar as chaves privadas no nosso ambiente, dessa maneira:

$ export PRIVATE_KEY_1='your private key 1 here'
$ export PRIVATE_KEY_2='your private key 2 here'
Enter fullscreen mode Exit fullscreen mode

Queremos salvar essas chaves privadas no nosso ambiente para que não precisemos deixá-las hardcoded no nosso arquivo. É uma prática ruim expôr uma chave privada dessa maneira. E se mandássemos as chaves para a fonte em um projeto real? Alguém poderia roubar nosso Ether! Agora queremos ler as chaves privadas do nosso ambiente e armazená-las em variáveis. Podemos fazer isso com o objeto global process do NodeJS:

const privateKey1 = process.env.PRIVATE_KEY_1
const privateKey2 = process.env.PRIVATE_KEY_2
Enter fullscreen mode Exit fullscreen mode

Para assinar transações com as chaves privadas, precisamos convertê-las em uma string de dados binários com um Buffer, um módulo disponível no NodeJS:

const privateKey1 = Buffer.from(process.env.PRIVATE_KEY_1)
const privateKey1 = Buffer.from(process.env.PRIVATE_KEY_2)
Enter fullscreen mode Exit fullscreen mode

Certo, agora temos todas as variáveis configuradas! Eu sei que um pouco disso pode parecer um pouco confuso agora. Mas fique comigo; tudo fará sentido daqui a pouco. :) Você também pode assistir o vídeo acima caso fique preso.

Nesse ponto, queremos fazer algumas coisas:

  1. Construir o objeto de uma transação
  2. Assinar a transação
  3. Enviar e transmitir a transação para a rede

Podemos criar um objeto de transação dessa maneira:

const txObject = {
    nonce:    web3.utils.toHex(txCount),
    to:       account2,
    value:    web3.utils.toHex(web3.utils.toWei('0.1', 'ether')),
    gasLimit: web3.utils.toHex(21000),
    gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei'))
  }
Enter fullscreen mode Exit fullscreen mode

Deixe-me explicar esse código. Estamos construindo um objeto que tem todos os valores necessários para criar uma transação, como o nonce, to, value, gasLimit e gasPrice. Vamos explicar cada um desses valores:

  • Nonce - esse é o contador de transações anteriores para uma conta. Vamos atribuir o valor dessa variável momentâneamente. Nós precisamos converter esse valor para hexadecimal. Podemos fazer isso com a utilidade do Web3.js web3.utils.toHex()
  • To - a conta para qual estamos mandando o Ether.
  • Value - a quantidade de Ether que queremos mandar. O valor deve ser expresso em Wei e convertido para hexadecimal. Podemos converter o valor para Wei com a utilidade Web3.js web.utils.toWei().
  • gasLimit - essa é a quantidade máxima de gas consumida pela transação. Uma transação básica como essa custa 21000 unidades de gas, então usaremos esse valor aqui.
  • gasPrice - essa é a quantidade que queremos pagar por cada unidade de gas. Usarei 10 Gwei aqui.

Note, que não existe um campo from nesse objeto de transação. Isso será inferido quando assinarmos a transação com a private key da conta 1.

Agora vamos atribuir o valor para a variável nonce. Podemos pegar o nonce da transação com a função web3.eth.getTransactionCount(). Vamos colocar nosso código dentro de uma função callback, dessa maneira:

web3.eth.getTransactionCount(account1, (err, txCount) => {
  const txObject = {
    nonce:    web3.utils.toHex(txCount),
    to:       account2,
    value:    web3.utils.toHex(web3.utils.toWei('0.1', 'ether')),
    gasLimit: web3.utils.toHex(21000),
    gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei'))
  }
})
Enter fullscreen mode Exit fullscreen mode

E aqui está um objeto completo de transação! Completamos o passo 1. Agora precisamos ir para o passo 2, no qual assinamos a transação. Podemos fazer isso assim:

const tx = new Tx(txObject)
tx.sign(privateKey1)

const serializedTx = tx.serialize()
const raw = '0x' + serializedTx.toString('hex')
Enter fullscreen mode Exit fullscreen mode

Aqui estamos usando a biblioteca etheremjs-tx para criar um novo objeto de transação. Também estamos usando essa biblioteca para assinar a transação com privateKey1. Depois, nós serializamos a transação e a convertemos para uma string hexadecimal, para que possa ser passada para o Web3.

Finalmente, vamos mandar a transação assinada e serializada para a rede de teste com a função web3.eth.sendSignedTransaction(), como essa:

web3.eth.sendSignedTransaction(raw, (err, txHash) => {
  console.log('txHash:', txHash)
})
Enter fullscreen mode Exit fullscreen mode

E pronto! Esse é o último passo desta aula que envia a transação e transmite-a para a rede. Nesse ponto, você completou o arquivo app.js, que deve se parecer com isso:

var Tx     = require('ethereumjs-tx')
const Web3 = require('web3')
const web3 = new Web3('https://ropsten.infura.io/YOUR_INFURA_API_KEY')

const account1 = '' // Your account address 1
const account2 = '' // Your account address 2

const privateKey1 = Buffer.from('YOUR_PRIVATE_KEY_1', 'hex')
const privateKey2 = Buffer.from('YOUR_PRIVATE_KEY_2', 'hex')

web3.eth.getTransactionCount(account1, (err, txCount) => {
  // Build the transaction
  const txObject = {
    nonce:    web3.utils.toHex(txCount),
    to:       account2,
    value:    web3.utils.toHex(web3.utils.toWei('0.1', 'ether')),
    gasLimit: web3.utils.toHex(21000),
    gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei'))
  }

  // Sign the transaction
  const tx = new Tx(txObject)
  tx.sign(privateKey1)

  const serializedTx = tx.serialize()
  const raw = '0x' + serializedTx.toString('hex')

  // Broadcast the transaction
  web3.eth.sendSignedTransaction(raw, (err, txHash) => {
    console.log('txHash:', txHash)
    // Now go check etherscan to see the transaction!
  })
})
Enter fullscreen mode Exit fullscreen mode

Você pode rodar o arquivo app.js do seu terminal com o NodeJS dessa maneira:

$ node app.js
Enter fullscreen mode Exit fullscreen mode

ou simplesmente:

$ node app
Enter fullscreen mode Exit fullscreen mode

Sinta-se livre para assistir o vídeo acima caso você fique preso! Você também pode baixar os códigos de exemplo no github.

# 4 - Fazendo o deploy de Smart contracts com Web3.js

Esse é o quarto vídeo da série de 8 tutoriais. Esse vídeo vai mostrar como fazer o deploy de smart contracts para a Blockchain Ethereum com Web3.js

https://youtu.be/msT3tpwnyv8

Existem várias maneiras de fazer o deploy de smart contracts para a Blockchain Ethereum. Existem até várias maneiras de fazer o deploy deles dentro do Web3.js. Como a aula anterior dessa série, vou demonstrar um método que vai ajudar você a entender melhor o quê acontece quando um smart contract é implantado na Blockchain Ethereum. Esse exemplo foi feito para desmontar o processo de deploy em vários passos.

Essa aula vai usar o mesmo arquivo app.js que usamos na aula anterior. Vamos configurá-lo dessa maneira:

var Tx = require('ethereumjs-tx')
const Web3 = require('web3')
const web3 = new Web3('https://ropsten.infura.io/YOUR_INFURA_API_KEY')

const account1 = '' // Your account address 1

const privateKey1 = Buffer.from('YOUR_PRIVATE_KEY_1', 'hex')
Enter fullscreen mode Exit fullscreen mode

Essa aula de exemplo consistirá nos três mesmos passos básicos das aulas passadas.

  1. Construir um objeto de transação
  2. Assinar a transação
  3. Enviar a transação

Esses passos são os mesmos porque quando escrevemos dados para a blockchain, sempre consiste nos mesmos passos básicos. Eu estou tentando mostrar que fazer o deploy de um smart contract se parece muito com mandar Ether de uma conta para outra, ou chamar uma função de smart contract. Ainda estamos construindo a transação e enviando para a rede. A única diferença são os parâmetros da transação.

Vamos em frente e construir o objeto de transação, dessa maneira:

const txObject = {
  nonce:    web3.utils.toHex(txCount),
  gasLimit: web3.utils.toHex(1000000), // Raise the gas limit to a much higher amount
  gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei')),
  data: data
}
Enter fullscreen mode Exit fullscreen mode

Estamos construindo o objeto da transação que tem muitos campos iguais ao objeto da missão anterior, como nonce, gasLimit e gasPrice. Também existem algumas diferenças de chaves. Vamos entender cada um desses:

  • Nonce - esse é o contador de transações anteriores para uma conta. O mesmo da aula anterior.
  • To - Esse parâmetro fica em branco pois não estamos mandando essa transação para uma conta em particular. Ao invés disso, estamos mandando-a para a rede toda, pois estamos fazendo o deploy de um smart contract.
  • Value - Esse parâmetro fica em branco nesse exemplo pois não estamos mandando nenhum Ether nessa transação.
  • gasLimit - essa é a quantidade máxima de gas consumida pela transação. Vamos aumentar esse limite pois fazer o deploy de um smart contract usa muito mais gas do que enviar Ether.
  • gasPrice - essa é a quantidade que queremos pagar por cada unidade de gas. O mesmo da aula anterior.
  • data - esse será o bytecode do smart contract que queremos fazer deploy. Vamos atribuir um valor para essa variável, o qual explicarei daqui a pouco.

Vamos falar sobre o parâmetro data. Esse é o bytecode compilado que representa o smart contract em hexadecimal. Para obter esse valor, primeiro precisamos de um smart contract, e depois precisamos compilá-lo. Você é bem vindo a usar qualquer contrato que quiser, especialmente se levarmos em conta que estamos fazendo deploy em uma rede de testes. Entretanto, eu vou usar um smart contract de um token ERC-20 que eu construí nesse vídeo. Você pode me acompanhar no vídeo acima para me assistir compilando o smart contract do ERC-20 com o Remix para obter essa string de dados. Uma vez que você compilou o seu contrato, você pode atribuir o valor de data em uma variável, dessa maneira:

const data = '0x60806040526040805190810160405280600a81526020017f4441707020546f6b656e000000000000000000000000000000000000000000008152506000908051906020019061004f92919061014e565b506040805190810160405280600481526020017f44415050000000000000000000000000000000000000000000000000000000008152506001908051906020019061009b92919061014e565b506040805190810160405280600f81526020017f4441707020546f6b656e2076312e300000000000000000000000000000000000815250600290805190602001906100e792919061014e565b503480156100f457600080fd5b506000620f4240905080600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080600381905550506101f3565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061018f57805160ff19168380011785556101bd565b828001600101855582156101bd579182015b828111156101bc5782518255916020019190600101906101a1565b5b5090506101ca91906101ce565b5090565b6101f091905b808211156101ec5760008160009055506001016101d4565b5090565b90565b610b99806102026000396000f300608060405260043610610099576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde031461009e578063095ea7b31461012e57806318160ddd1461019357806323b872dd146101be5780635a3b7e421461024357806370a08231146102d357806395d89b411461032a578063a9059cbb146103ba578063dd62ed3e1461041f575b600080fd5b3480156100aa57600080fd5b506100b3610496565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f35780820151818401526020810190506100d8565b50505050905090810190601f1680156101205780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561013a57600080fd5b50610179600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610534565b604051808215151515815260200191505060405180910390f35b34801561019f57600080fd5b506101a8610626565b6040518082815260200191505060405180910390f35b3480156101ca57600080fd5b50610229600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061062c565b604051808215151515815260200191505060405180910390f35b34801561024f57600080fd5b5061025861089b565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561029857808201518184015260208101905061027d565b50505050905090810190601f1680156102c55780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156102df57600080fd5b50610314600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610939565b6040518082815260200191505060405180910390f35b34801561033657600080fd5b5061033f610951565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561037f578082015181840152602081019050610364565b50505050905090810190601f1680156103ac5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103c657600080fd5b50610405600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506109ef565b604051808215151515815260200191505060405180910390f35b34801561042b57600080fd5b50610480600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b48565b6040518082815260200191505060405180910390f35b60008054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561052c5780601f106105015761010080835404028352916020019161052c565b820191906000526020600020905b81548152906001019060200180831161050f57829003601f168201915b505050505081565b600081600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60035481565b6000600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115151561067c57600080fd5b600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115151561070757600080fd5b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b60028054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109315780601f1061090657610100808354040283529160200191610931565b820191906000526020600020905b81548152906001019060200180831161091457829003601f168201915b505050505081565b60046020528060005260406000206000915090505481565b60018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109e75780601f106109bc576101008083540402835291602001916109e7565b820191906000526020600020905b8154815290600101906020018083116109ca57829003601f168201915b505050505081565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a3f57600080fd5b81600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a36001905092915050565b60056020528160005260406000206020528060005260406000206000915091505054815600a165627a7a723058204c3f690997294d337edc3571d8e77afc5b0e56a2f4bfae6fb59139c8e4eb2f7e0029'
Enter fullscreen mode Exit fullscreen mode

Agora também podemos atribuir o valor nonce buscando a contagem de transações, da mesma maneira que na aula anterior:

web3.eth.getTransactionCount(account1, (err, txCount) => {
  const data = '' // Your data value goes here...

  const txObject = {
    nonce:    web3.utils.toHex(txCount),
    gasLimit: web3.utils.toHex(1000000),
    gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei')),
    data: data
  }
})
Enter fullscreen mode Exit fullscreen mode

E por último, podemos assinar a transação e enviá-la, da mesma maneira que a aula anterior. Nesse ponto, código completo do tutorial deve parecer com isso:

var Tx = require('ethereumjs-tx')
const Web3 = require('web3')
const web3 = new Web3('https://ropsten.infura.io/YOUR_INFURA_API_KEY')

const account1 = '' // Your account address 1
const account2 = '' // Your account address 2

const privateKey1 = Buffer.from('YOUR_PRIVATE_KEY_1', 'hex')
const privateKey2 = Buffer.from('YOUR_PRIVATE_KEY_2', 'hex')

// Deploy the contract
web3.eth.getTransactionCount(account1, (err, txCount) => {
  const data = '0x60806040526040805190810160405280600a81526020017f4441707020546f6b656e000000000000000000000000000000000000000000008152506000908051906020019061004f92919061014e565b506040805190810160405280600481526020017f44415050000000000000000000000000000000000000000000000000000000008152506001908051906020019061009b92919061014e565b506040805190810160405280600f81526020017f4441707020546f6b656e2076312e300000000000000000000000000000000000815250600290805190602001906100e792919061014e565b503480156100f457600080fd5b506000620f4240905080600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080600381905550506101f3565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061018f57805160ff19168380011785556101bd565b828001600101855582156101bd579182015b828111156101bc5782518255916020019190600101906101a1565b5b5090506101ca91906101ce565b5090565b6101f091905b808211156101ec5760008160009055506001016101d4565b5090565b90565b610b99806102026000396000f300608060405260043610610099576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde031461009e578063095ea7b31461012e57806318160ddd1461019357806323b872dd146101be5780635a3b7e421461024357806370a08231146102d357806395d89b411461032a578063a9059cbb146103ba578063dd62ed3e1461041f575b600080fd5b3480156100aa57600080fd5b506100b3610496565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f35780820151818401526020810190506100d8565b50505050905090810190601f1680156101205780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561013a57600080fd5b50610179600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610534565b604051808215151515815260200191505060405180910390f35b34801561019f57600080fd5b506101a8610626565b6040518082815260200191505060405180910390f35b3480156101ca57600080fd5b50610229600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061062c565b604051808215151515815260200191505060405180910390f35b34801561024f57600080fd5b5061025861089b565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561029857808201518184015260208101905061027d565b50505050905090810190601f1680156102c55780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156102df57600080fd5b50610314600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610939565b6040518082815260200191505060405180910390f35b34801561033657600080fd5b5061033f610951565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561037f578082015181840152602081019050610364565b50505050905090810190601f1680156103ac5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103c657600080fd5b50610405600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506109ef565b604051808215151515815260200191505060405180910390f35b34801561042b57600080fd5b50610480600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b48565b6040518082815260200191505060405180910390f35b60008054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561052c5780601f106105015761010080835404028352916020019161052c565b820191906000526020600020905b81548152906001019060200180831161050f57829003601f168201915b505050505081565b600081600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60035481565b6000600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115151561067c57600080fd5b600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115151561070757600080fd5b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b60028054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109315780601f1061090657610100808354040283529160200191610931565b820191906000526020600020905b81548152906001019060200180831161091457829003601f168201915b505050505081565b60046020528060005260406000206000915090505481565b60018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109e75780601f106109bc576101008083540402835291602001916109e7565b820191906000526020600020905b8154815290600101906020018083116109ca57829003601f168201915b505050505081565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a3f57600080fd5b81600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a36001905092915050565b60056020528160005260406000206020528060005260406000206000915091505054815600a165627a7a723058204c3f690997294d337edc3571d8e77afc5b0e56a2f4bfae6fb59139c8e4eb2f7e0029'

  const txObject = {
    nonce:    web3.utils.toHex(txCount),
    gasLimit: web3.utils.toHex(1000000), // Raise the gas limit to a much higher amount
    gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei')),
    data: data
  }

  const tx = new Tx(txObject)
  tx.sign(privateKey1)

  const serializedTx = tx.serialize()
  const raw = '0x' + serializedTx.toString('hex')

  web3.eth.sendSignedTransaction(raw, (err, txHash) => {
    console.log('err:', err, 'txHash:', txHash)
    // Use this txHash to find the contract on Etherscan!
  })
})
Enter fullscreen mode Exit fullscreen mode

Agora você pode rodar o arquivo app.js do seu terminal com o NodeJS desse jeito:

$ node app.js
Enter fullscreen mode Exit fullscreen mode

Sinta-se livre para assistir o vídeo acima caso fique preso! Você também pode baixar todo o código de exemplo dessa série de tutoriais do github.

# 5 - Chamando funções de Smart Contracts com Web3.js

Esse é o quinto vídeo dessa série de tutoriais. Esse vídeo vai demonstrar como escrever dados para um smart contract com Web3.js

https://youtu.be/6HlHwCaAZKQ

Essa aula vai utilizar muitos dos passos básicos que fizemos nas aulas anteriores, porque foi feito para mostrar todos os passos básicos necessários quando criamos transações na Blockchain Ethereum. Vamos usar o mesmo setup com um arquivo app.js, que se parece com isso:

const Web3 = require('web3')
const web3 = new Web3('https://ropsten.infura.io/YOUR_INFURA_API_KEY')

const account1 = '' // Your account address 1
const account2 = '' // Your account address 2

const privateKey1 = Buffer.from('YOUR_PRIVATE_KEY_1', 'hex')
const privateKey2 = Buffer.from('YOUR_PRIVATE_KEY_2', 'hex')
Enter fullscreen mode Exit fullscreen mode

Também vamos criar um objeto de transação assim:

const txObject = {
  nonce:    web3.utils.toHex(txCount),
  gasLimit: web3.utils.toHex(800000),
  gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei')),
  to: contractAddress,
  data: data
}
Enter fullscreen mode Exit fullscreen mode

Se você está acompanhando as últimas aulas, muitos desses valores devem parecer familiares para você. Vamos notar algumas mudanças:

  • to - esse parâmetro vai ser o endereço do contrato implantado. Vamos obter esse valor e atribuí-lo daqui a pouco.
  • data - essa é a representação em hexadecimal da função que queremos chamar no smart contract. Vamos atribuir esse valor logo.

Para completar esse valores, precisaremos pegar o ABI do smart contract para esse token ERC-20. Você pode fazer a mesma coisa que eu no vídeo acima para obter o ABI no Remix. Também preciso pegar o endereço do smart contract no Etherscan (que está disponível a partir do momento que fizemos o deploy do contrato na última aula. Agora que temos as duas coisas, podemos criar uma representação JavaScript do smart contract dentro do Web3.js:

const contractAddress = '0xd03696B53924972b9903eB17Ac5033928Be7D3Bc'
const contractABI = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"standard","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}]

const contract = new web3.eth.Contract(abi, contractAddress)
Enter fullscreen mode Exit fullscreen mode

Ótimo! Agora temos uma representação JavaScript do contrato implantado. Agora podemos preencher o campo data da transação convertendo a função transfer() para bytecode (é a função que vamos chamar no smart contract). Podemos fazer isso com a função encodeABI() do Web3.js, que está disponível no objeto contract.

const data = contract.methods.transfer(account2, 1000).encodeABI()
Enter fullscreen mode Exit fullscreen mode

É isso! É fácil assim fazer o encode da chamada da função para a transação! Note que estamos transferindo 1,000 tokens para account2. Esse método cuida do encode dos parâmetros das funções para a gente também.

Isso é tudo que precisamos para construir o objeto da transação. Da mesma maneira que em aulas anteriores, nós podemos assinar essa transação e enviá-la. Uma vez que o fizermos, podemos mostrar os valores dos saldos das contas para ver se a função do smart contract foi chamada, e se a transferência de token foi completa. O código completo deve se parecer com isso:

const Web3 = require('web3')
const web3 = new Web3('https://ropsten.infura.io/YOUR_INFURA_API_KEY')

const account1 = '' // Your account address 1
const account2 = '' // Your account address 2

const privateKey1 = Buffer.from('YOUR_PRIVATE_KEY_1', 'hex')
const privateKey2 = Buffer.from('YOUR_PRIVATE_KEY_2', 'hex')

// Read the deployed contract - get the addresss from Etherscan
const contractAddress = '0xd03696B53924972b9903eB17Ac5033928Be7D3Bc'
const contractABI = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"standard","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}]

const contract = new web3.eth.Contract(abi, contractAddress)

// Transfer some tokens
web3.eth.getTransactionCount(account1, (err, txCount) => {

  const txObject = {
    nonce:    web3.utils.toHex(txCount),
    gasLimit: web3.utils.toHex(800000), // Raise the gas limit to a much higher amount
    gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei')),
    to: contractAddress,
    data: contract.methods.transfer(account2, 1000).encodeABI()
  }

  const tx = new Tx(txObject)
  tx.sign(privateKey1)

  const serializedTx = tx.serialize()
  const raw = '0x' + serializedTx.toString('hex')

  web3.eth.sendSignedTransaction(raw, (err, txHash) => {
    console.log('err:', err, 'txHash:', txHash)
    // Use this txHash to find the contract on Etherscan!
  })
})

// Check Token balance for account1
contract.methods.balanceOf(account1).call((err, balance) => {
  console.log({ err, balance })
})

// Check Token balance for account2
contract.methods.balanceOf(account2).call((err, balance) => {
  console.log({ err, balance })
})
Enter fullscreen mode Exit fullscreen mode

Agora você pode rodar o arquivo app.js no seu terminal com NodeJS:

$ node app.js
Enter fullscreen mode Exit fullscreen mode

Sinta-se livre para assistir o vídeo acima caso fique preso! Você também pode baixar todo o código de exemplo dessa série de tutoriais do github.

# 6 - Eventos de Smart Contract com Web3.js

Esse é o sexto vídeo dessa série de tutoriais. Esse vídeo vai mostrar como examinar eventos de smart contracts na Blockchain Ethereum com Web3.js.

https://youtu.be/CX2QOE0FcEo

Os smart contracts Ethereum têm a habilidade de emitir eventos que indicam que algo aconteceu dentro da execução do smart contract. Os consumidores têm a habilidade de observar esses eventos, e o Web3.js nos dará essa funcionalidade. Isso é exatamente o que vamos cobrir nessa aula.

Vamos continuar utilizando um smart contract ERC-20 como ponto de referência para esse tutorial, porque o padrão especifica que o smart contract deve emitir um evento Transfer toda vez que um token ERC-20 é transferido. Vamos precisar nos conectar com a rede principal da Ethereum e assistir o evento Transfer do token ERC-20 OmiseGo.

Vamos configurar o arquivo app.js como fizemos nas aulas anteriores. Dessa vez, vamos nos conectar com a rede principal da Ethereum. Vou colar o ABI e endereço do smart contract do OmiseGo, que pode ser obtido pelo Etherscan (assista o vídeo acima para mais instruções). Uma vez que tivermos essas duas coisas, podemos criar uma representação JavaScript do smart contract com o Web3.js e atribuir a uma variável. Todo o setup vai se parecer assim:

const Web3 = require('web3')
const web3 = new Web3('https://mainnet.infura.io/YOUR_INFURA_API_KEY')

// OMG Token Contract
const abi = [{"constant":true,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_releaseTime","type":"uint256"}],"name":"mintTimelocked","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[],"name":"MintFinished","type":"event"},{"anonymous":false,"inputs":[],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]
const address = '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07'

const contract = new web3.eth.Contract(abi, address)
Enter fullscreen mode Exit fullscreen mode

Agora podemos olhar para eventos passados para esse smart contract com a função getPastEvents() disponível no objeto do nosso contrato. Primeiro. vamos pegar todos os eventos emitidos pelo contrato:

contract.getPastEvents(
  'AllEvents',
  {
    fromBlock: 0,
    toBlock: 'latest'
  },
  (err, events) => { console.log(events) }
)
Enter fullscreen mode Exit fullscreen mode

Aqui, essa função leva dois argumentos: o nome do evento e um conjunto de parâmetros de filtro. Nós especificamos que queremos ouvir todos os eventos passando AllEvents. Vamos especificar um evento daqui a pouco. Depois, passamos alguns parâmetros de filtro para especificar que queremos os eventos da vida inteira do contrato passando from: 0 ou o primeiro bloco da Blockchain, e toBlock: latest ou o último bloco da Blockchain. Só uma nota, se você rodar esse código, a execução provavelmente falhará, porque a lista de eventos é muito grande para esse contrato.

Vamos mirar uma execução de sucesso limitando o número de blocos que queremos buscar. Podemos passar um fromBlock mais recente, dessa maneira:

contract.getPastEvents(
  'AllEvents',
  {
    fromBlock: 5854000,
    toBlock: 'latest'
  },
  (err, events) => { console.log(events) }
)
Enter fullscreen mode Exit fullscreen mode

Assim, muito melhor. Agora, podemos especificar também que queremos ouvir apenas o evento Transfer, dessa maneira:

contract.getPastEvents(
  'Transfer',
  {
    fromBlock: 5854000,
    toBlock: 'latest'
  },
  (err, events) => { console.log(events) }
)
Enter fullscreen mode Exit fullscreen mode

E é isso! Esse é todo o código que você precisa para ver todos os eventos de transferência recentes para o token ERC-20 OmiseGo. Com esse código, você pode construir algo como um histórico de transações para o token OMG em uma wallet cripto. Esse é o poder do Web3.js. Nesse ponto, o código completo do tutorial está assim:

const Web3 = require('web3')
const web3 = new Web3('https://mainnet.infura.io/YOUR_INFURA_API_KEY')

// OMG Token Contract
const abi = [{"constant":true,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_releaseTime","type":"uint256"}],"name":"mintTimelocked","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[],"name":"MintFinished","type":"event"},{"anonymous":false,"inputs":[],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]
const address = '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07'

const contract = new web3.eth.Contract(abi, address)

// Get Contract Event Stream
contract.getPastEvents(
  'AllEvents',
  {
    fromBlock: 5854000,
    toBlock: 'latest'
  },
  (err, events) => { console.log(events) }
)
Enter fullscreen mode Exit fullscreen mode

Você pode rodar o app do seu terminal com o NodeJS assim:

$ node app.js
Enter fullscreen mode Exit fullscreen mode

Sinta-se livre para assistir o vídeo acima caso fique preso! Você também pode baixar todo o código de exemplo dessa série de tutoriais do github.

# 7 - Inspecionando Blocos com Web3.js

Esse é o sétimo vídeo dessa série de tutoriais. Esse vídeo vai mostrar como inspecionar blocos da blockchain Ethereum com Web3.js.

https://youtu.be/DFCCcgr9dAQ

Inspecionar blocos é muito útil para analisar históricos na Blockchain Ethereum. O Web3.js tem muitas funcionalidades que nos ajudam a fazer isso. Por exemplo, nós podemos construir algo que se parece com um histórico de blocos como o do Etherscan:

Image description

Vamos configurar um arquivo app.js para começar a usar essa funcionalidade do Web3.js. Essa configuração será bem mais simples do que as aulas anteriores. Vamos nos conectar à rede principal para inspecionar os blocos:

const Web3 = require('web3')
const web3 = new Web3('https://mainnet.infura.io/YOUR_INFURA_API_KEY')
Enter fullscreen mode Exit fullscreen mode

Primeiro, podemos pegar o número do último bloco:

web3.eth.getBlockNumber().then(console.log)
Enter fullscreen mode Exit fullscreen mode

Também podemos pegar todos os dados do último bloco, assim:

web3.eth.getBlock('latest').then(console.log)
Enter fullscreen mode Exit fullscreen mode

Você pode assistir o vídeo acima, em que eu explico todos os dados que são logados.

Se fôssemos construir um histórico de blocos como o do Etherscan, precisaríamos pegar uma lista dos blocos mais recentes da rede. Podemos fazer isso buscando o bloco mais recente e contando de trás para frente até termos os últimos 10 blocos da rede. Podemos fazer um for loop assim:

web3.eth.getBlockNumber().then((latest) => {
  for (let i = 0; i < 10; i++) {
    web3.eth.getBlock(latest - i).then(console.log)
  }
})
Enter fullscreen mode Exit fullscreen mode

O Web3.js tem outra ferramenta que nos permite inspecionar transações contidas em um bloco específico. Podemos fazer isso assim:

const hash = '0x66b3fd79a49dafe44507763e9b6739aa0810de2c15590ac22b5e2f0a3f502073'
web3.eth.getTransactionFromBlock(hash, 2).then(console.log)
Enter fullscreen mode Exit fullscreen mode

É isso! É fácil assim inspecionar blocos com Web3.js. Dê uma olhada no vídeo acima para explicações mais profundas sobre os dados retornados pelos blocos. Nesse ponto, todo o código do tutorial deve se parecer assim:

const Web3 = require('web3')
const web3 = new Web3('https://mainnet.infura.io/YOUR_INFURA_API_KEY')

// get latest block number
web3.eth.getBlockNumber().then(console.log)

// // get latest block
web3.eth.getBlock('latest').then(console.log)

// get latest 10 blocks
web3.eth.getBlockNumber().then((latest) => {
  for (let i = 0; i < 10; i++) {
    web3.eth.getBlock(latest - i).then(console.log)
  }
})

// get transaction from specific block
const hash = '0x66b3fd79a49dafe44507763e9b6739aa0810de2c15590ac22b5e2f0a3f502073'
web3.eth.getTransactionFromBlock(hash, 2).then(console.log)
Enter fullscreen mode Exit fullscreen mode

Você pode rodar o app do seu terminal com o NodeJS assim:

$ node app.js
Enter fullscreen mode Exit fullscreen mode

Sinta-se livre para assistir o vídeo acima caso fique preso! Você também pode baixar todo o código de exemplo dessa série de tutoriais do github.

# 8 - Utilidades Web3.js

Esse é o oitavo e último vídeo dessa série de tutoriais. Esse vídeo vai mostrar como utilizar as utilidades incluídas no Web3.js e dicas e truques bônus.

https://youtu.be/C5Kv77_AUFE

Essa aula foi feita para mostrar algumas dicas e truques que você pode não saber sobre o Web3.js! Vamos em frente e configurar o app.js, e dar uma olhada nessas dicas. Vamos nos conectar com a rede principal Ethereum:

const Web3 = require('web3')
const web3 = new Web3('https://mainnet.infura.io/YOUR_INFURA_API_KEY')
Enter fullscreen mode Exit fullscreen mode

Primeiro, você pode pegar o preço médio atual de gas da rede assim:

web3.eth.getGasPrice().then((result) => {
  console.log(web3.utils.fromWei(result, 'ether')
})
Enter fullscreen mode Exit fullscreen mode

Se você já desenvolveu na blockchain anteriormente, você já deve ter lidado com funções de hashing. Web3.js tem muitos helpers para usar essas funções. Você tem acesso direto à função sha3:

console.log(web3.utils.sha3('Dapp University'))
Enter fullscreen mode Exit fullscreen mode

Ou à função keccack256:

console.log(web3.utils.keccak256('Dapp University'))
Enter fullscreen mode Exit fullscreen mode

Você também pode mexer com pseudo aleatoriedade gerando um hexadecimal aleatório de 32 bytes:

console.log(web3.utils.randomHex(32))
Enter fullscreen mode Exit fullscreen mode

Você já se encontrou tentando performar uma ação em uma array ou objeto JavaScript e precisou de ajuda de uma biblioteca externa? O Web3 também tem a biblioteca underscoreJS:

const _ = web3.utils._
_.each({ key1: 'value1', key2: 'value2' }, (value, key) => {
  console.log(key)
})
Enter fullscreen mode Exit fullscreen mode

E é isso! Essas são algumas dicas que você pode utilizar com o Web3.js.

Aqui está o código completo desta aula:

const Web3 = require('web3')
const web3 = new Web3('https://mainnet.infura.io/YOUR_INFURA_API_KEY')

// Get average gas price in wei from last few blocks median gas price
web3.eth.getGasPrice().then((result) => {
  console.log(web3.utils.fromWei(result, 'ether')
})

// Use sha256 Hashing function
console.log(web3.utils.sha3('Dapp University'))

// Use keccak256 Hashing function (alias)
console.log(web3.utils.keccak256('Dapp University'))

// Get a Random Hex
console.log(web3.utils.randomHex(32))

// Get access to the underscore JS biblioteca
const _ = web3.utils._

_.each({ key1: 'value1', key2: 'value2' }, (value, key) => {
  console.log(key)
})
Enter fullscreen mode Exit fullscreen mode

Você pode rodar o app do seu terminal com o NodeJS assim:

$ node app.js
Enter fullscreen mode Exit fullscreen mode

Sinta-se livre para assistir o vídeo acima caso fique preso! Você também pode baixar todo o código de exemplo dessa série de tutoriais do github.

Top comments (0)