Biblioteca JavaScript Ethers.js¶
Introdução¶
A biblioteca Ethers.js fornece ferramentas para interagir com nós Ethereum usando JavaScript, semelhante à Web3.js. As redes EVM alimentadas pela Tanssi oferecem uma API compatível com Ethereum/JSON-RPC, então você pode usar Ethers.js para interagir com uma rede EVM da Tanssi como faria no Ethereum. Para mais detalhes, consulte a documentação oficial.
Neste guia você aprenderá a usar Ethers.js na sua rede EVM da Tanssi. Para demonstrar, enviaremos uma transação e implantaremos um contrato em uma appchain EVM de demonstração rodando no Dancelight. Para sua própria appchain Tanssi, basta trocar o endpoint.
Se preferir vídeo, veja os tutoriais no topo desta página sobre Enviar transações com Ethers.js e Implantar contratos com Ethers.js.
Note
Os exemplos deste guia partem de um ambiente MacOS ou Ubuntu 20.04. Se estiver usando Windows, adapte os comandos conforme necessário.
Verifique também se você tem o Node.js e um gerenciador de pacotes (como npm ou yarn) instalados. Para saber como instalar o Node.js, consulte a documentação oficial.
Além disso, certifique-se de ter inicializado um arquivo package.json para módulos ES6. Você pode criar um package.json padrão com npm executando npm init --yes.
Verificando pré-requisitos¶
Para os exemplos deste guia você precisará:
- De uma conta com fundos na rede EVM da Tanssi que estiver usando para testes
Instalando Ethers.js¶
Instale a biblioteca Ethers.js e o compilador Solidity:
npm install ethers solc@0.8.0
yarn add ethers solc@0.8.0
Configurando o provedor Ethers¶
Os scripts a seguir usam um provedor Ethers para falar com a rede.
- Importe
ethers - Defina
providerRPCcomname,rpcechainIdda rede - Crie o
providercomethers.JsonRpcProvider
// 1. Importe ethers
import { ethers } from "ethers";
// 2. Defina as configurações da rede
const providerRPC = {
evmNetwork: {
name: 'dancelight-evm-network',
// Insira aqui sua URL RPC
rpc: 'https://services.tanssi-testnet.network/dancelight-2001/',
chainId: 5678, // 0x162E em hexadecimal,
},
};
// 3. Crie o provider do ethers
const provider = new ethers.JsonRpcProvider(
providerRPC.evmNetwork.rpc,
{
chainId: providerRPC.evmNetwork.chainId,
name: providerRPC.evmNetwork.name,
}
);
Guarde este trecho; ele é reutilizado nos scripts abaixo.
Enviar uma transação¶
Criaremos dois scripts: um para consultar saldos e outro para enviar a transação.
Script de saldos¶
Crie o arquivo:
touch balances.js
Depois monte o script:
- Inclua o provedor
- Defina
addressFromeaddressTo - Crie a função
balances - Use
provider.getBalanceeethers.formatEtherpara exibir os saldos - Chame
balances()
// 1. Adicione aqui a lógica do provider do Ethers:
// {...}
// 2. Crie as variáveis de endereço
const addressFrom = 'INSERT_ADDRESS_FROM';
const addressTo = 'INSERT_ADDRESS_TO';
// 3. Crie a função de saldos
const balances = async () => {
// 4. Busque os saldos
const balanceFrom = ethers.formatEther(await provider.getBalance(addressFrom));
const balanceTo = ethers.formatEther(await provider.getBalance(addressTo));
console.log(`The balance of ${addressFrom} is: ${balanceFrom} TANGO`);
console.log(`The balance of ${addressTo} is: ${balanceTo} TANGO`);
};
// 5. Chamar a função de saldos
balances();
Ver o script completo
// Import ethers
import { ethers } from 'ethers';
// Define network configurations
const providerRPC = {
evmNetwork: {
name: 'dancelight-evm-network',
rpc: 'https://services.tanssi-testnet.network/dancelight-2001', // Insert your RPC URL here
chainId: 5678, // 0x162E in hex,
},
};
// Create ethers provider
const provider = new ethers.JsonRpcProvider(providerRPC.evmNetwork.rpc, {
chainId: providerRPC.evmNetwork.chainId,
name: providerRPC.evmNetwork.name,
});
// Define addresses
const addressFrom = 'INSERT_ADDRESS_FROM';
const addressTo = 'INSERT_ADDRESS_TO';
// Create balances function
const balances = async () => {
// Fetch balances
const balanceFrom = ethers.formatEther(
await provider.getBalance(addressFrom)
);
const balanceTo = ethers.formatEther(await provider.getBalance(addressTo));
console.log(`The balance of ${addressFrom} is: ${balanceFrom} TANGO`);
console.log(`The balance of ${addressTo} is: ${balanceTo} TANGO`);
};
// Call the balances function
balances();
Execute:
node balances.js
Saldos serão exibidos em TANGO.
The balance of 0x8841701Dba3639B254D9CEe712E49D188A1e941e is: 1.0 TANGO
Script de envio de transação¶
Crie o arquivo:
touch transaction.js
Passos:
- Inclua o provedor
- Defina
privateKeyeaddressTo(não armazene chaves reais em arquivos JS) - Crie a wallet com
privateKeyeprovider - Crie a função
send - Monte o objeto de transação (
to,valuecomethers.parseEther) - Envie com
wallet.sendTransactione aguarde o recibo - Chame
send()
// 1. Adicione aqui a lógica do provider do Ethers:
// {...}
// 2. Crie as variáveis da conta
const accountFrom = {
privateKey: 'INSERT_YOUR_PRIVATE_KEY',
};
const addressTo = 'INSERT_ADDRESS_TO';
// 3. Crie a wallet
let wallet = new ethers.Wallet(accountFrom.privateKey, provider);
// 4. Crie a função de envio
const send = async () => {
console.log(`Attempting to send transaction from ${wallet.address} to ${addressTo}`);
// 5. Crie o objeto da tx
const tx = {
to: addressTo,
value: ethers.parseEther('1'),
};
// 6. Assine e envie a tx — aguarde o recibo
const createReceipt = await wallet.sendTransaction(tx);
await createReceipt.wait();
console.log(`Transaction successful with hash: ${createReceipt.hash}`);
};
// 7. Chame a função de envio
send();
Ver o script completo
// Import ethers
import { ethers } from 'ethers';
// Define network configurations
const providerRPC = {
evmNetwork: {
name: 'dancelight-evm-network',
rpc: 'https://services.tanssi-testnet.network/dancelight-2001', // Insert your RPC URL here
chainId: 5678, // 0x162E in hex,
},
};
// Create ethers provider
const provider = new ethers.JsonRpcProvider(providerRPC.evmNetwork.rpc, {
chainId: providerRPC.evmNetwork.chainId,
name: providerRPC.evmNetwork.name,
});
// Define accounts and wallet
const accountFrom = {
privateKey: 'INSERT_YOUR_PRIVATE_KEY',
};
const addressTo = 'INSERT_ADDRESS_TO';
const wallet = new ethers.Wallet(accountFrom.privateKey, provider);
// Create send function
const send = async () => {
console.log(
`Attempting to send transaction from ${wallet.address} to ${addressTo}`
);
// Create transaction
const tx = {
to: addressTo,
value: ethers.parseEther('1'),
};
// Send transaction and get hash
const createReceipt = await wallet.sendTransaction(tx);
await createReceipt.wait();
console.log(`Transaction successful with hash: ${createReceipt.hash}`);
};
// Call the send function
send();
Rode com:
node transaction.js
O hash será exibido. Use balances.js antes/depois para confirmar a mudança de saldo.
Transaction successful with hash: 0x29d87c00704b949cb4cc04fdc6c98d53b3c0ec4fb3ffe0c52864a73 b586f563c node balances.js The balance of 0x44236223aB4291b93EEd10E4B511B37a398DEE55 is: 18.999958 TANGO
The balance of 0x8841701Dba3639B254D9CEe712E49D188A1e941e is: 2.0 TANGO
Implantar um contrato¶
O contrato que você irá compilar e implantar nas próximas seções é um simples incrementador, chamado Incrementer.sol. Comece criando o arquivo do contrato:
touch Incrementer.sol
Depois, adicione o código Solidity ao arquivo:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Incrementer {
uint256 public number;
constructor(uint256 _initialNumber) {
number = _initialNumber;
}
function increment(uint256 _value) public {
number = number + _value;
}
function reset() public {
number = 0;
}
}
A função constructor, executada quando o contrato é implantado, define o valor inicial da variável number armazenada on-chain (padrão é 0). A função increment soma o _value informado ao número atual, mas exige uma transação, pois modifica o dado armazenado. Por fim, a função reset zera o valor armazenado.
Note
Este contrato é apenas um exemplo simples para fins ilustrativos.
Script de compilação¶
Nesta seção, você criará um script que usa o compilador Solidity para gerar o bytecode e a interface (ABI) do contrato Incrementer.sol. Para começar, crie o arquivo compile.js executando:
touch compile.js
Em seguida, escreva o script e conclua estas etapas:
- Importe os pacotes
fsesolc - Use
fs.readFileSyncpara ler e salvar o conteúdo deIncrementer.solemsource - Monte o objeto
inputpara o compilador Solidity especificandolanguage,sourcesesettings - Compile o contrato usando
solc.compilecom o objetoinput - Extraia o contrato compilado e exporte-o para ser usado no script de implantação
// 1. Import packages
import fs from 'fs';
import solc from 'solc';
// 2. Get path and load contract
const source = fs.readFileSync('Incrementer.sol', 'utf8');
// 3. Create input object
const input = {
language: 'Solidity',
sources: {
'Incrementer.sol': {
content: source,
},
},
settings: {
outputSelection: {
'*': {
'*': ['*'],
},
},
},
};
// 4. Compile the contract
const tempFile = JSON.parse(solc.compile(JSON.stringify(input)));
const contractFile = tempFile.contracts['Incrementer.sol']['Incrementer'];
// 5. Export contract data
export default contractFile;
Script de deploy¶
Compile Incrementer.sol e depois crie deploy.js:
touch deploy.js
Passos:
- Importe o contrato de
compile.js - Inclua o provedor
- Defina
privateKey(não salve chaves reais em JS) - Guarde
bytecodeeabi - Crie a wallet
- Crie a
ContractFactory - Crie a função
deploy - Use
incrementer.deploy(5)e aguarde o recibo - Chame
deploy()
// 1. Importe o arquivo do contrato
import contractFile from './compile';
// 2. Adicione aqui a lógica do provider do Ethers:
// {...}
// 3. Crie as variáveis da conta
const accountFrom = {
privateKey: 'INSERT_YOUR_PRIVATE_KEY',
};
// 4. Salve o bytecode e o ABI
const bytecode = contractFile.evm.bytecode.object;
const abi = contractFile.abi;
// 5. Crie a wallet
let wallet = new ethers.Wallet(accountFrom.privateKey, provider);
// 6. Crie a instância do contrato com o assinante
const incrementer = new ethers.ContractFactory(abi, bytecode, wallet);
// 7. Crie a função de deploy
const deploy = async () => {
console.log(`Attempting to deploy from account: ${wallet.address}`);
// 8. Envie a tx (valor inicial definido como 5) e aguarde o recibo
const contract = await incrementer.deploy(5);
const txReceipt = await contract.deploymentTransaction().wait();
console.log(`Contract deployed at address: ${txReceipt.contractAddress}`);
};
// 9. Chame a função de deploy
deploy();
Ver o script completo
// Import ethers and compile
import { ethers } from 'ethers';
import contractFile from './compile.js';
// Define network configurations
const providerRPC = {
evmNetwork: {
name: 'dancelight-evm-network',
rpc: 'https://services.tanssi-testnet.network/dancelight-2001', // Insert your RPC URL here
chainId: 5678, // 0x162E in hex,
},
};
// Create ethers provider
const provider = new ethers.JsonRpcProvider(providerRPC.evmNetwork.rpc, {
chainId: providerRPC.evmNetwork.chainId,
name: providerRPC.evmNetwork.name,
});
// Define accounts and wallet
const accountFrom = {
privateKey: 'INSERT_YOUR_PRIVATE_KEY',
};
let wallet = new ethers.Wallet(accountFrom.privateKey, provider);
// Load contract info
const bytecode = contractFile.evm.bytecode.object;
const abi = contractFile.abi;
// Create contract instance with signer
const incrementer = new ethers.ContractFactory(abi, bytecode, wallet);
// Create deploy function
const deploy = async () => {
console.log(`Attempting to deploy from account: ${wallet.address}`);
// Send tx (initial value set to 5) and wait for receipt
const contract = await incrementer.deploy(5);
const txReceipt = await contract.deploymentTransaction().wait();
console.log(`Contract deployed at address: ${txReceipt.contractAddress}`);
};
// Call the deploy function
deploy();
Execute:
node deploy.js
O endereço do contrato será exibido.
Contract deployed at address: 0x2EF0C649C08D55637dec9fCcebCFeD27F2F2a5F2
Ler dados do contrato (calls)¶
Calls não alteram estado; nenhuma transação é enviada. Crie get.js:
touch get.js
Passos:
- Importe o
contractFiledecompile.js - Inclua o provedor
- Defina
contractAddress - Crie a instância com
ethers.Contract - Crie a função
get - Chame
incrementer.number()e exiba o valor - Chame
get()
// 1. Importe o ABI do contrato
import contractFile from './compile';
// 2. Adicione aqui a lógica do provider do Ethers:
// {...}
// 3. Variável do endereço do contrato
const contractAddress = 'INSERT_CONTRACT_ADDRESS';
// 4. Crie a instância do contrato
const incrementer = new ethers.Contract(
contractAddress,
contractFile.abi,
provider
);
// 5. Crie a função get
const get = async () => {
console.log(`Fazendo uma chamada para o contrato no endereço: ${contractAddress}`);
// 6. Chame o contrato
const data = await incrementer.number();
console.log(`The current number stored is: ${data}`);
};
// 7. Chame a função get
get();
Ver o script completo
// Import ethers and compile
import { ethers } from 'ethers';
import contractFile from './compile.js';
// Define network configurations
const providerRPC = {
evmNetwork: {
name: 'dancelight-evm-network',
rpc: 'https://services.tanssi-testnet.network/dancelight-2001', // Insert your RPC URL here
chainId: 5678, // 0x162E in hex,
},
};
// Create ethers provider
const provider = new ethers.JsonRpcProvider(providerRPC.evmNetwork.rpc, {
chainId: providerRPC.evmNetwork.chainId,
name: providerRPC.evmNetwork.name,
});
// Contract address variable
const contractAddress = 'INSERT_CONTRACT_ADDRESS';
// Create contract instance
const incrementer = new ethers.Contract(
contractAddress,
contractFile.abi,
provider
);
// Create get function
const get = async () => {
console.log(`Making a call to contract at address: ${contractAddress}`);
// Call contract
const data = await incrementer.number();
console.log(`The current number stored is: ${data}`);
};
// Call get function
get();
Rode com:
node get.js
The current number stored is: 5
Interagir com o contrato (send)¶
Sends alteram estado e exigem transação. Crie increment.js e reset.js:
touch increment.js reset.js
increment.js:
- Importe
contractFile - Inclua o provedor
- Defina
privateKey,contractAddress,_value(não salve chaves reais em JS) - Crie a wallet
- Crie a instância do contrato com signer
- Crie a função
increment - Chame
incrementer.increment(_value)e aguarde recibo - Chame
increment()
// 1. Importe o ABI do contrato
import contractFile from './compile';
// 2. Adicione aqui a lógica do provider do Ethers:
// {...}
// 3. Crie as variáveis
const accountFrom = {
privateKey: 'INSERT_YOUR_PRIVATE_KEY',
};
const contractAddress = 'INSERT_CONTRACT_ADDRESS';
const _value = 3;
// 4. Crie a wallet
let wallet = new ethers.Wallet(accountFrom.privateKey, provider);
// 5. Crie a instância do contrato com o assinante
const incrementer = new ethers.Contract(
contractAddress,
contractFile.abi,
wallet
);
// 6. Crie a função de incremento
const increment = async () => {
console.log(
`Chamando a função de incremento por ${_value} no contrato no endereço: ${contractAddress}`
);
// 7. Assine e envie a tx e aguarde o recibo
const createReceipt = await incrementer.increment(_value);
await createReceipt.wait();
console.log(`Tx successful with hash: ${createReceipt.hash}`);
};
// 8. Chame a função de incremento
increment();
Ver o script completo
// Import ethers and compile
import { ethers } from 'ethers';
import contractFile from './compile.js';
// Define network configurations
const providerRPC = {
evmNetwork: {
name: 'dancelight-evm-network',
rpc: 'https://services.tanssi-testnet.network/dancelight-2001', // Insert your RPC URL here
chainId: 5678, // 0x162E in hex,
},
};
// Create ethers provider
const provider = new ethers.JsonRpcProvider(providerRPC.evmNetwork.rpc, {
chainId: providerRPC.evmNetwork.chainId,
name: providerRPC.evmNetwork.name,
});
// Create variables
const accountFrom = {
privateKey: 'INSERT_YOUR_PRIVATE_KEY',
};
const contractAddress = 'INSERT_CONTRACT_ADDRESS';
const _value = 3;
// Create wallet
let wallet = new ethers.Wallet(accountFrom.privateKey, provider);
// Create contract instance with signer
const incrementer = new ethers.Contract(
contractAddress,
contractFile.abi,
wallet
);
// Create increment function
const increment = async () => {
console.log(
`Calling the increment by ${_value} function in contract at address: ${contractAddress}`
);
// Sign and send tx and wait for receipt
const createReceipt = await incrementer.increment(_value);
await createReceipt.wait();
console.log(`Tx successful with hash: ${createReceipt.hash}`);
};
// Call the increment function
increment();
reset.js:
- Importe
contractFile - Inclua o provedor
- Defina
privateKeyecontractAddress - Crie a wallet
- Crie a instância do contrato com signer
- Crie a função
reset - Chame
incrementer.reset()e aguarde recibo - Chame
reset()
// 1. Importe o ABI do contrato
import contractFile from './compile';
// 2. Adicione aqui a lógica do provider do Ethers:
// {...}
// 3. Crie as variáveis
const accountFrom = {
privateKey: 'INSERT_YOUR_PRIVATE_KEY',
};
const contractAddress = 'INSERT_CONTRACT_ADDRESS';
// 4. Crie a wallet
let wallet = new ethers.Wallet(accountFrom.privateKey, provider);
// 5. Crie a instância do contrato com o assinante
const incrementer = new ethers.Contract(
contractAddress,
contractFile.abi,
wallet
);
// 6. Crie a função de reset
const reset = async () => {
console.log(`Chamando a função de reset no contrato no endereço: ${contractAddress}`);
// 7. Assine e envie a tx e aguarde o recibo
const createReceipt = await incrementer.reset();
await createReceipt.wait();
console.log(`Tx successful with hash: ${createReceipt.hash}`);
};
// 8. Chame a função de reset
reset();
Ver o script completo
// Import ethers and compile
import { ethers } from 'ethers';
import contractFile from './compile.js';
// Define network configurations
const providerRPC = {
evmNetwork: {
name: 'dancelight-evm-network',
rpc: 'https://services.tanssi-testnet.network/dancelight-2001', // Insert your RPC URL here
chainId: 5678, // 0x162E in hex,
},
};
// Create ethers provider
const provider = new ethers.JsonRpcProvider(providerRPC.evmNetwork.rpc, {
chainId: providerRPC.evmNetwork.chainId,
name: providerRPC.evmNetwork.name,
});
// Create variables
const accountFrom = {
privateKey: 'INSERT_YOUR_PRIVATE_KEY',
};
const contractAddress = 'INSERT_CONTRACT_ADDRESS';
// Create wallet
let wallet = new ethers.Wallet(accountFrom.privateKey, provider);
// Create contract instance with signer
const incrementer = new ethers.Contract(
contractAddress,
contractFile.abi,
wallet
);
// Create reset function
const reset = async () => {
console.log(
`Calling the reset function in contract at address: ${contractAddress}`
);
// Sign and send tx and wait for receipt
const createReceipt = await incrementer.reset();
await createReceipt.wait();
console.log(`Tx successful with hash: ${createReceipt.hash}`);
};
// Call the reset function
reset();
Rode:
node increment.js
node reset.js
Use get.js junto para confirmar a mudança de valor.
Tx successful with hash: 0xb689da50a43e98b5a83ff64757afbf100be12e2db6ff4d0504168f262cc08fb0 node get.js Making a call to contract at address: 0x2EF0C649C08D55637dec9fCcebCFeD27F2F2a5F2
The current number stored is: 0
| Criada: 9 de dezembro de 2025