JavaScript

17 mar, 2023

Como migrar projetos do Ethers v5 para Ethers v6

Publicidade

Hoje no mercado de programação web3 existem duas bibliotecas que são muito utilizadas em projetos JavaScript, quer seja no frontend, seja no backend: a mais antiga Web3.js e a mais moderna EthersJS. E assim como tivemos uma grande evolução que quebrou muita coisa quando a Web3.js saiu da sua versão 1 para a v2, aconteceu o mesmo recentemente com a Ethers mudando da v5 para v6.

Escrevo este post da maneira que eu gostaria de ter encontrado na Internet quando precisei atualizar aplicações da Ethers 5 para Ethers 6 e espero que lhe ajude também. Algumas mudanças são sutis e possivelmente você já resolveu sozinho, outras são mais grosseiras mesmo e afetam principalmente usuários de TypeScript, que é mais sensível a estas mudanças de tipos. Não é para ser um post extenso e ao mesmo tempo ele deve ser atualizado ao longo do tempo, conforme vou aprendendo mais sobre EthersJS v6.

Se preferir, o vídeo abaixo possui praticamente o mesmo conteúdo.

Mudanças da v5 para v6

A maior parte das mudanças são simples, pois correspondem a mudanças na estrutura de pastas da biblioteca. De fato até a versão 5 eu sentia a biblioteca um tanto verbosa e com um uso excessivo da pasta utils, sendo esta uma das principais mudanças: não tem mais a pasta utils. Tudo que estava na utils agora está direto ethers.x. Ou seja:

O mesmo vale para os providers. Antes tínhamos de especificar o caminho passando por providers, agora não é mais necessário, chamamos os providers diretamente a partir do objeto ethers.

Falando em providers, outra mudança que me impactou foi a mudança de nome do Web3Provider para BrowserProvider. Confesso que ficou um excelente nome, já que ele serve justamente para integração com as carteiras de browser como metaMask (saiba mais sobre aqui), mas ainda assim é uma breaking change que afetou meus projetos aqui. Então se juntarmos a alteração anterior e essa, teremos:

Ainda no âmbito dos providers é a alteração da função provider.getSigner, usada para nos prepararmos para assinar transações para a blockchain. Antes, a função getSigner era sync, agora ela é async e retorna uma promise, então cuidado com isso pois sabemos que interfere bastante no fluxo de execução (saiba mais sobre async aqui).

Além disso, além dessa mudança para pegar o signer do provider, para quem usa TypeScript tivemos algumas mudanças de type definitions que afetam a integração com Smart Contracts. Como esse, do ABI de um contrato que antes era ContractInterface e agora é InterfaceAbi.

E certamente devem ter outros types que mudaram, esse é um dos que eu fui impactado em meus projetos.

Números Gigantes

Agora saindo dos providers, vamos falar de números gigantes ou Big Numbers/Big Ints. Antes a biblioteca ethers usava uma biblioteca de terceiros para representação de números gigantes no JavaScript (biblioteca BigNumber), algo extremamente necessário no contexto de criptomoedas onde é comum ter números astronômicos na faixa de 18 dígitos. Como JavaScript possui suporte a bigint nativamente desde a versão 2020 da linguagem, era uma questão de tempo até que as bibliotecas começassem a se adaptar e foi isso o que aconteceu com o Ethers na sua versão 6.

A primeira coisa que você deve fazer é, se estiver usando TypeScript, alterar no tsconfig.json para que a versão-alvo do Ecmascript (target) seja a es2020, que tem suporte a bigint. Isso vai te permitir, além de usar o tipo bigint, usar a notação 1n, onde 1 é o numeral e ‘n’ indica que este é um número gigante (bigint), sendo tratado em memória de maneira diferente ao number tradicional.

Agora as alterações de BigNumber para o novo padrão devem ser feitas da seguinte forma: primeiro, na tipagem via TS (types ou interfaces), quando você tinha um campo gigante usava BigNumber, agora deve usar BigNumberish, que oferece um suporte mais flexível, incluindo ao bigint nativo.

No entanto, uma vez que você use o novo tipo BigNumberish e abandone de vez a lib BigNumber usada na v5 em prol do bigint nativo da v6, você deverá mudar as funções de conversão que você usava, como por exemplo as que convertem para número gigante:

E o contrário também vale, quando você tem um BigNumberish e quer devolver para number (nos casos em que isso é possível, é claro):

E por enquanto estas são as alterações que tive de fazer em meus projetos e que resolvi compartilhar com vocês, para ajudá-los na atualização dos seus. Espero ter ajudado e até a próxima!