Ethers.js
Já vimos como Ă© possĂvel interagir com o Ethereum utilizando JSON-RPC. No entanto, existem bibliotecas que facilitam essa interação, pois permitem incluir chamadas diretamente no cĂłdigo das aplicações com instruções que utilizam JSON-RPC por trás.
Uma das bibliotecas mais conhecidas Ă© o ethers.js, que Ă© escrito em JavaScript. Assim como ela, existem outras em JavaScript (Web3.js) e em outras linguagens como Python (Web3py).
No nosso caso, utilizaremos o ethers.js, pois Ă© o mais utilizado atualmente.
Realizando chamadas JSON-RPC com ethers.js
Vamos ver como começar a utilizar o ethers.js. Lembre-se de que, como executaremos código JavaScript, precisamos ter o node.js e o npm instalados (veja os pré-requisitos deste módulo).
Posicione-se no repositório do seu projeto antes de iniciar a instalação.
Instalar o
ethers.js
:npm init npm install ethers
Certifique-se de que os componentes associados à instalação foram criados no seu diretório:
Um diretĂłrio
node_modules/
que contém todos os módulos instalados, incluindo a pastaethers
.Um arquivo
package-lock.json
que descreve as versões exatas das dependências instaladas.Seu arquivo
package.json
deve conter oethers
na seção de dependências.
Obter uma URL de acesso ao Ethereum de um provedor de serviços de acesso a nós:
No nosso caso, utilizaremos o Alchemy. Utilize a URL que obteve na seção anterior, que tem a seguinte estrutura: “https://eth-mainnet.g.alchemy.com/v2/YOUR_ALCHEMY_PROJECT_ID”.
Escrever um script para se conectar e fazer chamadas JSON-RPC:
Crie um arquivo
index.js
no VS Code e adicione o seguinte cĂłdigo:const { ethers } = require("ethers"); // Substitua pela sua URL do Alchemy const alchemyUrl = '<https://eth-mainnet.g.alchemy.com/v2/YOUR_ALCHEMY_PROJECT_ID>'; // Crie um provedor usando a URL do Alchemy const provider = new ethers.JsonRpcProvider(alchemyUrl); // Obtenha o nĂşmero do bloco atual async function getBlockNumber() { try { const blockNumber = await provider.getBlockNumber(); console.log("NĂşmero de bloque actual:", blockNumber); } catch (e) { console.error("Error al obtener el nĂşmero de bloque", e); } } getBlockNumber();
Neste primeiro script, obtemos o nĂşmero do Ăşltimo bloco criado no Ethereum.
Detalhando a estrutura deste script:
Importamos a biblioteca ethers.js.
Definimos que nos conectaremos via HTTPS com um provedor de serviço de nós como o Alchemy e especificamos a URL para a conexão.
Criamos um novo
JsonRpcProvider
utilizando a URL do Alchemy. Um provedor no ethers.js Ă© um objeto que se conecta a um nĂł do Ethereum e permite realizar diversas chamadas Ă blockchain, como obter o nĂşmero do bloco atual, enviar transações, etc.Definimos uma função assĂncrona chamada
getBlockNumber
. Dentro da função, usamosawait provider.getBlockNumber()
para obter o nĂşmero do bloco atual da blockchain. A palavra-chaveawait
faz com que a função espere até que a promessa seja resolvida e retorna o resultado. Se a chamada for bem-sucedida, o número do bloco é impresso no console. Se houver um erro durante a chamada, ele é capturado no blococatch
e uma mensagem de erro é impressa no console.Executamos a função
getBlockNumber
.
<aside> ⚠️ Este script usa a versão 6 do ethers.js. Se você estiver utilizando uma versão anterior, é muito provável que obtenha um erro.</aside>
Executar o Script:
bashCopiar cĂłdigo
node index.js
Escrever um script para obter o saldo de uma conta:
Execute este cĂłdigo utilizando o node.js para obter o saldo de uma conta.
javascriptCopiar cĂłdigo
const { ethers } = require("ethers"); // Substitua pela sua URL do Alchemy const alchemyUrl = '<https://eth-mainnet.g.alchemy.com/v2/YOUR_ALCHEMY_PROJECT_ID>'; // Crie um provedor usando a URL do Alchemy const provider = new ethers.JsonRpcProvider(alchemyUrl); // Indique a conta que se quer conhecer o saldo const address = "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"; // Obtenha o saldo da conta async function getBalance() { try { const balance = await provider.getBalance(address); console.log("Saldo de la cuenta:", ethers.formatEther(balance), "ETH"); } catch (e) { console.error("Error al obtener el saldo de la cuenta", e); } } getBalance();
<aside> 👨🏻‍💻 Desafio: Utilizando este código, modifique o endereço para obter o saldo da conta pública de Vitalik.
</aside>
O archivo .env
Quando precisarmos fazer uma chamada Ă blockchain que envolva realizar uma escrita, será necessário assinar as transações e, para isso, Ă© preciso utilizar a chave privada da nossa carteira. NĂŁo podemos expor nossa chave privada ou, em geral, qualquer informação sensĂvel. Qual Ă© a solução? Utilizar uma combinação de um arquivo .env
(lido como "dot i-en-vi") e um arquivo .gitignore
.
Um .env
Ă© um arquivo de texto que contĂ©m pares chave-valor, onde cada par representa uma variável de ambiente. Esses arquivos sĂŁo utilizados para configurar aplicações de forma que a configuração especĂfica do ambiente (por exemplo, desenvolvimento, teste, produção) possa ser mantida fora do cĂłdigo-fonte e carregada dinamicamente conforme necessário.
Por que utilizar um arquivo .env
?
Segurança: Manter chaves de API e outras credenciais fora do código-fonte ajuda a prevenir sua exposição acidental.
Flexibilidade: Permite alterar configurações facilmente sem modificar o código.
Portabilidade: Facilita a configuração do ambiente em diferentes máquinas e ambientes (desenvolvimento, testes, produção).
Passos para utilizar um arquivo .env
em um programa JavaScript:
1. Instalar o dotenv
Primeiro, vocĂŞ precisa instalar a biblioteca dotenv
, que carrega as variáveis de ambiente de um arquivo .env
para process.env
.
npm install dotenv
2. Criar um archivo .env
Na raiz do seu projeto, crie um arquivo chamado .env
. Este arquivo conterá suas variáveis de ambiente. Por exemplo:
ALCHEMY_URL=https://eth-mainnet.g.alchemy.com/v2/YOUR_ALCHEMY_PROJECT_ID
API_KEY=your_api_key
PORT=3000
3. Carregar variáveis de ambiente na sua aplicação
No seu arquivo principal JavaScript (por exemplo, index.js
), carregue as variáveis de ambiente usando o dotenv
e sentenças do tipo process.env.VARIABLE_NAME
para incorporar os valores das variáveis do arquivo .env
à sua aplicação.
// Importar dotenv
require('dotenv').config();
// Acessando variáveis ​​de ambiente
const alchemyUrl = process.env.ALCHEMY_URL;
const apiKey = process.env.API_KEY;
const port = process.env.PORT;
console.log(`Alchemy URL: ${alchemyUrl}`);
console.log(`API Key: ${apiKey}`);
console.log(`Port: ${port}`);
4. Utilizar as variáveis de ambiente no seu código
Você pode utilizar essas variáveis de ambiente na sua aplicação. Por exemplo, nosso script para obter o número do bloco atual utilizando um arquivo .env
seria o seguinte:
const { ethers } = require('ethers');
require('dotenv').config();
const alchemyUrl = process.env.ALCHEMY_URL;
const provider = new ethers.JsonRpcProvider(alchemyUrl);
async function getBlockNumber() {
try {
const blockNumber = await provider.getBlockNumber();
console.log('NĂşmero de bloque actual:', blockNumber);
} catch (e) {
console.error('Error al obtener el nĂşmero de bloque', e);
}
}
getBlockNumber();
5. Usar um arquivo .gitignore
Certifique-se de adicionar seu arquivo .env
ao arquivo .gitignore
para que ele nĂŁo seja enviado ao seu repositĂłrio Git e suas credenciais nĂŁo sejam expostas acidentalmente.
.env
node_modules
E a estrutura do seu repositĂłrio deve ser semelhante a esta:
mi-proyecto/
├── .env
├── .gitignore
├── index.js
└── package.json
Com esses passos, sua aplicação pode usar variáveis de ambiente definidas em um arquivo .env
, mantendo a configuração flexĂvel e segura.
Fazer uma chamada de escrita em Sepolia
Agora vamos ver como devemos proceder para executar uma transação que implica uma alteração na blockchain.
Neste exemplo, faremos a transferĂŞncia de ETH de uma conta para outra dentro da rede Sepolia. Para isso, precisamos ter o seguinte:
Uma URL de acesso à Sepolia no formato: https://eth-sepolia.g.alchemy.com/v2/TU_ACCESO (você deve obtê-la de forma semelhante à da mainnet em um serviço como o Alchemy).
A chave privada da wallet de origem dos fundos.
O endereço de destino dos fundos.
Incluir os dados da URL de acesso e da chave privada no arquivo .env.
const { ethers } = require('ethers');
require('dotenv').config();
// URL do provedor Sepolia do arquivo .env
const sepoliaUrl = process.env.SEPOLIA_URL;
// Crie um provedor usando a URL da Sepolia
const provider = new ethers.JsonRpcProvider(sepoliaUrl);
// Carregue a carteira a partir de uma chave privada
const privateKey = process.env.PRIVATE_KEY;
const wallet = new ethers.Wallet(privateKey, provider);
async function sendTransaction() {
const tx = {
to: 'TARGET_ADDRESS', // Endereço de destino que você deve especificar
value: ethers.parseEther('0.1'), // quantidade a enviar em ETH
gasLimit: 21000,
// gasPrice: opcional, você pode deixar o fornecedor determinar o preço apropriado
};
try {
const txResponse = await wallet.sendTransaction(tx);
console.log('TransacciĂłn enviada:', txResponse.hash);
// Aguarde a validação da transação
const receipt = await txResponse.wait();
console.log('Transação validada:', receipt);
} catch (e) {
console.error('Error ao enviar a transação', e);
}
}
sendTransaction();
Chamadas mais usadas no ethers.js
Provedores (providers)
Criação de um provedor
const provider = new ethers.JsonRpcProvider(url);
Obter o nĂşmero do bloco atual
const blockNumber = await provider.getBlockNumber();
Obter o saldo de um endereço
const balance = await provider.getBalance(address);
Obter informações de um bloco
const block = await provider.getBlock(blockNumber);
Obter o histórico de transações de um endereço
const history = await provider.getHistory(address);
Obter o preço do gás
const gasPrice = await provider.getGasPrice();
Obter uma transação
const tx = await provider.getTransaction(transactionHash);
Obter o status de uma transação
const txReceipt = await provider.getTransactionReceipt(txHash);
Wallets
Criar uma carteira aleatĂłria
const wallet = ethers.Wallet.createRandom(); console.log("Address:", wallet.address);//para ver a conta console.log("Private Key:", wallet.privateKey); //para ver a chave privada
Carregar uma carteira a partir de uma chave privada
const wallet = new ethers.Wallet(privateKey);
Conectar uma carteira a um provedor
const connectedWallet = wallet.connect(provider);
Assinar uma mensagem
const signedMessage = await wallet.signMessage(message);
Enviar uma transação
const txResponse = await wallet.sendTransaction(transaction);
Utilitários
Converter Ether para Wei
const weiAmount = ethers.parseEther("1.0");
Converter Wei para Ether
const etherAmount = ethers.formatEther(weiAmount);
Calcular o hash de uma mensagem
const messageHash = ethers.hashMessage(message);
Obter o endereço de um contrato a partir de seu bytecode
const contractAddress = ethers.getContractAddress(transaction);
Contratos
Conectar a um contrato
const contract = new ethers.Contract(contractAddress, abi, provider);
Chamar uma função somente leitura
const result = await contract.someReadOnlyFunction();
Enviar uma transação para uma função de escrita
const txResponse = await contract.someWriteFunction(params, { gasLimit, gasPrice });
Ouvir eventos de um contrato
contract.on("EventName", (param1, param2, event) => { console.log(param1, param2, event); });
Last updated