Uma introdução ao Ethereum para desenvolvedores Python, parte 1
Então, você ouviu falar sobre esse tal de Ethereum e está pronto para entrar na toca do coelho? Esta publicação abordará rapidamente alguns conceitos básicos de blockchain e, em seguida, fará com que você interaja com um nó simulado do Ethereum – lendo dados de blocos, verificando saldos de contas e enviando transações. Ao longo do caminho, destacaremos as diferenças entre as formas tradicionais de criar aplicativos e esse novo paradigma descentralizado.
Pré-requisitos (básicos)
Esta publicação aspira ser acessível a uma ampla gama de desenvolvedores. Ferramentas Python estarão envolvidas, mas elas são apenas um veículo para as ideias – não há problema se você não for um desenvolvedor Python. No entanto, farei apenas algumas suposições sobre o que você já sabe, para que possamos passar rapidamente para as partes específicas do Ethereum.
Suposições:
- Você sabe se virar em um terminal,
- Você já escreveu algumas linhas de código Python,
- A versão 3.6 ou superior do Python está instalada em sua máquina (o uso de um ambiente virtual (opens in a new tab) é altamente recomendado), e
- você já usou o
pip, o instalador de pacotes do Python. Novamente, se alguma dessas afirmações não for verdadeira, ou se você não planeja reproduzir o código neste artigo, provavelmente ainda poderá acompanhar sem problemas.
Blockchains, resumidamente
Existem muitas maneiras de descrever o Ethereum, mas em sua essência há uma blockchain. As blockchains são compostas por uma série de blocos, então vamos começar por aí. Nos termos mais simples, cada bloco na blockchain do Ethereum é apenas alguns metadados e uma lista de transações. No formato JSON, isso se parece com algo assim:
{
"number": 1234567,
"hash": "0xabc123...",
"parentHash": "0xdef456...",
...,
"transactions": [...]
}
Cada bloco tem uma referência ao bloco que o antecedeu; o parentHash é simplesmente o hash do bloco anterior.
Uma blockchain é essencialmente uma lista vinculada; cada bloco tem uma referência ao bloco anterior.
Essa estrutura de dados não é nenhuma novidade, mas as regras (ou seja, protocolos ponto a ponto) que governam a rede são. Não há autoridade central; a rede de pares deve colaborar para sustentar a rede e competir para decidir quais transações incluir no próximo bloco. Portanto, quando você quiser enviar algum dinheiro a um amigo, precisará transmitir essa transação para a rede e aguardar que ela seja incluída em um bloco futuro.
A única maneira de a blockchain verificar se o dinheiro foi realmente enviado de um usuário para outro é usar uma moeda nativa (ou seja, criada e governada por) dessa blockchain. No Ethereum, essa moeda é chamada de ether, e a blockchain do Ethereum contém o único registro oficial de saldos de contas.
Um novo paradigma
Essa nova pilha de tecnologia descentralizada gerou novas ferramentas para desenvolvedores. Essas ferramentas existem em muitas linguagens de programação, mas analisaremos através da lente do Python. Para reiterar: mesmo que Python não seja sua linguagem de escolha, não deve ser muito difícil acompanhar.
Os desenvolvedores Python que desejam interagir com o Ethereum provavelmente recorrerão à Web3.py (opens in a new tab). A Web3.py é uma biblioteca que simplifica muito a maneira como você se conecta a um nó do Ethereum e, em seguida, envia e recebe dados dele.
Os clientes Ethereum podem ser configurados para serem acessíveis por IPC (opens in a new tab), HTTP ou Websockets, portanto, a Web3.py precisará espelhar essa configuração. A Web3.py se refere a essas opções de conexão como provedores (providers). Você vai querer escolher um dos três provedores para vincular a instância da Web3.py ao seu nó.
Configure o nó do Ethereum e a Web3.py para se comunicarem por meio do mesmo protocolo, por exemplo, IPC neste diagrama.
Quando a Web3.py estiver configurada corretamente, você poderá começar a interagir com a blockchain. Aqui estão alguns exemplos de uso da Web3.py como uma prévia do que está por vir:
# ler dados do bloco:
w3.eth.get_block('latest')
# enviar uma transação:
w3.eth.send_transaction({'from': ..., 'to': ..., 'value': ...})
Instalação
Neste passo a passo, trabalharemos apenas dentro de um interpretador Python. Não criaremos diretórios, arquivos, classes ou funções.
$ devem ser executados no terminal. (Não digite o $, ele apenas significa o início da linha.)Primeiro, instale o IPython (opens in a new tab) para ter um ambiente amigável para explorar. O IPython oferece preenchimento com a tecla Tab, entre outros recursos, tornando muito mais fácil ver o que é possível dentro da Web3.py.
pip install ipython
A Web3.py é publicada sob o nome web3. Instale-a assim:
pip install web3
Mais uma coisa – vamos simular uma blockchain mais tarde, o que requer mais algumas dependências. Você pode instalá-las via:
pip install 'web3[tester]'
Você está pronto para começar!
Nota: O pacote web3[tester] funciona até o Python 3.10.xx
Crie um ambiente de testes (sandbox)
Abra um novo ambiente Python executando ipython em seu terminal. Isso é comparável a executar python, mas vem com mais recursos e facilidades.
ipython
Isso imprimirá algumas informações sobre as versões do Python e do IPython que você está executando e, em seguida, você deverá ver um prompt aguardando entrada:
In [1]:
Você está olhando para um shell interativo do Python agora. Essencialmente, é um ambiente de testes (sandbox) para brincar. Se você chegou até aqui, é hora de importar a Web3.py:
In [1]: from web3 import Web3
Apresentando o módulo Web3
Além de ser uma porta de entrada para o Ethereum, o módulo Web3 (opens in a new tab) oferece algumas funções de conveniência. Vamos explorar algumas.
Em um aplicativo Ethereum, você normalmente precisará converter denominações de moeda. O módulo Web3 fornece alguns métodos auxiliares apenas para isso: from_wei (opens in a new tab) e to_wei (opens in a new tab).
Nota: Os computadores são notoriamente ruins em lidar com matemática decimal. Para contornar isso, os desenvolvedores costumam armazenar valores em dólares em centavos. Por exemplo, um item com preço de US$ 5,99 pode ser armazenado no banco de dados como 599.
Um padrão semelhante é usado ao lidar com transações em ether. No entanto, em vez de duas casas decimais, o ether tem 18! A menor denominação de ether é chamada de Wei, portanto, esse é o valor especificado ao enviar transações.
1 ether = 1000000000000000000 Wei
1 Wei = 0.000000000000000001 ether
Tente converter alguns valores de e para Wei. Observe que existem nomes para muitas das denominações (opens in a new tab) entre ether e Wei. Uma das mais conhecidas entre elas é o gwei, pois geralmente é assim que as taxas de transação são representadas.
In [2]: Web3.to_wei(1, 'ether')
Out[2]: 1000000000000000000
In [3]: Web3.from_wei(500000000, 'gwei')
Out[3]: Decimal('0.5')
Outros métodos utilitários no módulo Web3 incluem conversores de formato de dados (por exemplo, toHex (opens in a new tab)), auxiliares de endereço (por exemplo, isAddress (opens in a new tab)) e funções de hash (por exemplo, keccak (opens in a new tab)). Muitos deles serão abordados mais adiante na série. Para visualizar todos os métodos e propriedades disponíveis, utilize o preenchimento automático do IPython digitando Web3. e pressionando a tecla Tab duas vezes após o ponto.
Fale com a cadeia
Os métodos de conveniência são adoráveis, mas vamos passar para a blockchain. A próxima etapa é configurar a Web3.py para se comunicar com um nó do Ethereum. Aqui temos a opção de usar os provedores IPC, HTTP ou Websocket.
Não seguiremos por esse caminho, mas um exemplo de um fluxo de trabalho completo usando o provedor HTTP pode ser algo assim:
- Baixe um nó do Ethereum, por exemplo, Geth (opens in a new tab).
- Inicie o Geth em uma janela de terminal e aguarde a sincronização da rede. A porta HTTP padrão é
8545, mas é configurável. - Diga à Web3.py para se conectar ao nó via HTTP, em
localhost:8545.w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545')) - Use a instância
w3para interagir com o nó.
Embora essa seja uma maneira "real" de fazer isso, o processo de sincronização leva horas e é desnecessário se você deseja apenas um ambiente de desenvolvimento. A Web3.py expõe um quarto provedor para essa finalidade, o EthereumTesterProvider. Esse provedor de testes se vincula a um nó simulado do Ethereum com permissões relaxadas e moeda falsa para brincar.
O EthereumTesterProvider se conecta a um nó simulado e é útil para ambientes de desenvolvimento rápido.
Esse nó simulado é chamado de eth-tester (opens in a new tab) e nós o instalamos como parte do comando pip install web3[tester]. Configurar a Web3.py para usar esse provedor de testes é tão simples quanto:
In [4]: w3 = Web3(Web3.EthereumTesterProvider())
Agora você está pronto para surfar na cadeia! Isso não é algo que as pessoas dizem. Eu acabei de inventar isso. Vamos fazer um tour rápido.
O tour rápido
Primeiro as coisas mais importantes, uma verificação de sanidade:
In [5]: w3.is_connected()
Out[5]: True
Como estamos usando o provedor de testes, este não é um teste muito valioso, mas se falhar, é provável que você tenha digitado algo errado ao instanciar a variável w3. Verifique novamente se você incluiu os parênteses internos, ou seja, Web3.EthereumTesterProvider().
Parada do tour nº 1: contas
Por conveniência, o provedor de testes criou algumas contas e as pré-carregou com ether de teste.
Primeiro, vamos ver uma lista dessas contas:
In [6]: w3.eth.accounts
Out[6]: ['0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
'0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF',
'0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69', ...]
Se você executar este comando, deverá ver uma lista de dez strings que começam com 0x. Cada um é um endereço público e é, de certa forma, análogo ao número da conta em uma conta corrente. Você forneceria esse endereço a alguém que quisesse lhe enviar ether.
Como mencionado, o provedor de testes pré-carregou cada uma dessas contas com algum ether de teste. Vamos descobrir quanto há na primeira conta:
In [7]: w3.eth.get_balance(w3.eth.accounts[0])
Out[7]: 1000000000000000000000000
São muitos zeros! Antes de sair rindo até o banco falso, lembre-se daquela lição sobre denominações de moeda de antes. Os valores de ether são representados na menor denominação, Wei. Converta isso para ether:
In [8]: w3.from_wei(1000000000000000000000000, 'ether')
Out[8]: Decimal('1000000')
Um milhão de ether de teste — ainda não é nada mau.
Parada do tour nº 2: dados do bloco
Vamos dar uma olhada no estado desta blockchain simulada:
In [9]: w3.eth.get_block('latest')
Out[9]: AttributeDict({
'number': 0,
'hash': HexBytes('0x9469878...'),
'parentHash': HexBytes('0x0000000...'),
...
'transactions': []
})
Muitas informações são retornadas sobre um bloco, mas apenas algumas coisas a destacar aqui:
- O número do bloco é zero — não importa há quanto tempo você configurou o provedor de testes. Ao contrário da rede Ethereum real, que adiciona um novo bloco a cada 12 segundos, esta simulação aguardará até que você dê a ela algum trabalho a fazer.
transactionsé uma lista vazia, pelo mesmo motivo: ainda não fizemos nada. Este primeiro bloco é um bloco vazio, apenas para iniciar a cadeia.- Observe que o
parentHashé apenas um monte de bytes vazios. Isso significa que é o primeiro bloco da cadeia, também conhecido como bloco gênesis.
Parada do tour nº 3: transações
Estamos presos no bloco zero até que haja uma transação pendente, então vamos fornecer uma. Envie alguns ethers de teste de uma conta para outra:
In [10]: tx_hash = w3.eth.send_transaction({
'from': w3.eth.accounts[0],
'to': w3.eth.accounts[1],
'value': w3.to_wei(3, 'ether'),
'gas': 21000
})
Este é normalmente o ponto em que você esperaria vários segundos para que sua transação fosse incluída em um novo bloco. O processo completo é mais ou menos assim:
- Envie uma transação e guarde o hash da transação. Até que o bloco contendo a transação seja criado e transmitido, a transação fica "pendente".
tx_hash = w3.eth.send_transaction({ … }) - Aguarde a transação ser incluída em um bloco:
w3.eth.wait_for_transaction_receipt(tx_hash) - Continue a lógica do aplicativo. Para visualizar a transação bem-sucedida:
w3.eth.get_transaction(tx_hash)
Nosso ambiente simulado adicionará a transação em um novo bloco instantaneamente, para que possamos visualizar a transação imediatamente:
In [11]: w3.eth.get_transaction(tx_hash)
Out[11]: AttributeDict({
'hash': HexBytes('0x15e9fb95dc39...'),
'blockNumber': 1,
'transactionIndex': 0,
'from': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
'to': '0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF',
'value': 3000000000000000000,
...
})
Você verá alguns detalhes familiares aqui: os campos from, to e value devem corresponder às entradas da nossa chamada send_transaction. A outra parte tranquilizadora é que essa transação foi incluída como a primeira transação ('transactionIndex': 0) dentro do bloco número 1.
Também podemos verificar facilmente o sucesso dessa transação verificando os saldos das duas contas envolvidas. Três ethers devem ter sido movidos de uma para a outra.
In [12]: w3.eth.get_balance(w3.eth.accounts[0])
Out[12]: 999996999979000000000000
In [13]: w3.eth.get_balance(w3.eth.accounts[1])
Out[13]: 1000003000000000000000000
O último parece bom! O saldo passou de 1.000.000 para 1.000.003 ether. Mas o que aconteceu com a primeira conta? Parece ter perdido um pouco mais de três ethers. Infelizmente, nada na vida é de graça, e usar a rede pública do Ethereum exige que você compense seus pares por seu papel de apoio. Uma pequena taxa de transação foi deduzida da conta que enviou a transação - essa taxa é a quantidade de gás queimado (21.000 unidades de gás para uma transferência de ETH) multiplicada por uma taxa básica que varia de acordo com a atividade da rede, mais uma taxa de prioridade que vai para o validador que inclui a transação em um bloco.
Mais sobre gás
E respire
Já estamos nisso há algum tempo, então este parece ser um lugar tão bom quanto qualquer outro para fazer uma pausa. A toca do coelho continua, e continuaremos explorando na parte dois desta série. Alguns conceitos que estão por vir: conexão a um nó real, contratos inteligentes e tokens. Tem perguntas de acompanhamento? Avise-me! Seu feedback influenciará para onde iremos a partir daqui. Solicitações são bem-vindas via Twitter (opens in a new tab).
Última atualização da página: 3 de março de 2026


