Biblioteca viem TypeScript Ethereum¶
Introdução¶
viem é uma biblioteca TypeScript modular que fornece abstrações sobre a API JSON-RPC, facilitando a interação com nós Ethereum. Como as redes EVM da Tanssi expõem uma API compatível com Ethereum/JSON-RPC, você pode usar viem para interagir com qualquer rede EVM Tanssi. Veja a documentação do viem para mais detalhes.
Neste guia, você verá como usar viem para enviar uma transação e implantar um contrato na rede EVM de demonstração. O mesmo fluxo se aplica a qualquer rede EVM da Tanssi.
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, você precisará de:
- Uma conta com fundos na rede EVM Tanssi que estiver usando
Instalando viem¶
Crie um projeto TypeScript básico e instale dependências:
mkdir viem-examples && cd viem-examples && npm init --y
Instale viem e o compilador Solidity:
npm install typescript ts-node viem solc@0.8.0
yarn add typescript ts-node viem solc@0.8.0
Gere o tsconfig:
npx tsc --init
Nota
Tutorial criado usando Node.js v18.18.0.
Configurar um cliente viem (provedor)¶
Você pode criar: - um cliente de leitura com createPublicClient, para saldos/dados; ou - um cliente de escrita com createWalletClient, para enviar transações.
Primeiro defina a cadeia com defineChain, informando todos os campos (incluindo public e default RPC).
Para ler dados da cadeia¶
Passos:
- Importe
createPublicClient,httpedefineChaindeviem. - Defina os detalhes da cadeia (inclua URLs
publicedefault). - Crie o
clientcomcreatePublicClient, passando rede e RPC HTTP.
// 1. Import the necessary components from viem
import { createPublicClient, http, defineChain } from 'viem';
// 2. Specify the details of your EVM network
export const demoEVM = defineChain({
id: 5678,
name: 'demo',
network: 'demo',
nativeCurrency: {
decimals: 18,
name: 'TANGO',
symbol: 'TANGO',
},
rpcUrls: {
default: {
http: ['https://services.tanssi-testnet.network/dancelight-2001'],
webSocket: ['wss://services.tanssi-testnet.network/dancelight-2001'],
},
public: {
http: ['https://services.tanssi-testnet.network/dancelight-2001'],
webSocket: ['wss://services.tanssi-testnet.network/dancelight-2001'],
},
},
blockExplorers: {
default: {
name: 'Explorer',
url: 'https://dancelight-2001-blockscout.tanssi-chains.network/',
},
},
});
// 3. Create a public client for reading chain data
const rpcUrl = 'https://services.tanssi-testnet.network/dancelight-2001';
const publicClient = createPublicClient({
chain: demoEVM,
transport: http(rpcUrl),
});
Para gravar dados da cadeia¶
Passos:
- Importe
createWalletClient,http,defineChaindeviemeprivateKeyToAccountdeviem/accounts. - Defina os detalhes da cadeia (inclua URLs
publicedefault). - Crie a conta com
privateKeyToAccount. - Crie o
clientcomcreateWalletClient, passando conta, rede e RPC HTTP.
Remember
Demonstração apenas. Nunca salve chave privada em arquivo TypeScript.
// 1. Import the necessary components from viem and viem/accounts
import { createWalletClient, http, defineChain } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
// 2. Specify the details of your EVM network
export const demoEVM = defineChain({
id: 5678,
name: 'demo',
network: 'demo',
nativeCurrency: {
decimals: 18,
name: 'TANGO',
symbol: 'TANGO',
},
rpcUrls: {
default: {
http: ['https://services.tanssi-testnet.network/dancelight-2001'],
webSocket: ['wss://services.tanssi-testnet.network/dancelight-2001'],
},
public: {
http: ['https://services.tanssi-testnet.network/dancelight-2001'],
webSocket: ['wss://services.tanssi-testnet.network/dancelight-2001'],
},
},
blockExplorers: {
default: {
name: 'Explorer',
url: 'https://dancelight-2001-blockscout.tanssi-chains.network/',
},
},
});
// 3. Create your account using the privateKeyToAccount function
const account = privateKeyToAccount('INSERT_PRIVATE_KEY');
const rpcUrl = 'https://services.tanssi-testnet.network/dancelight-2001';
//4. Create a wallet client for writing chain data
const walletClient = createWalletClient({
account,
chain: demoEVM,
transport: http(rpcUrl),
});
Nota
Para carteiras de navegador, veja este exemplo (onde demo é a rede definida em defineChain):
const [account] = await window.ethereum.request({
method: 'eth_requestAccounts',
});
const walletClient = createWalletClient({
account,
chain: demo,
transport: custom(window.ethereum),
});
Enviar uma transação¶
Criaremos dois scripts: um para saldos e outro para enviar a transação.
Script de saldos¶
Crie o arquivo:
touch balances.ts
Passos:
- Importe
createPublicClient,http,formatEther,defineChain. - Defina a cadeia (inclua URLs
public/default). - Configure o cliente público.
- Defina
addressFromeaddressTo. - Crie a função
balancesusandopublicClient.getBalance. - Formate com
formatEthere exiba. - Chame
balances().
Ver balances.ts
// 1. Import the necessary components from viem
import { createPublicClient, http, formatEther, defineChain } from 'viem';
// 2. Specify the details of your EVM network
export const demoEVM = defineChain({
id: 5678,
name: 'demo',
network: 'demo',
nativeCurrency: {
decimals: 18,
name: 'UNIT',
symbol: 'UNIT',
},
rpcUrls: {
default: {
http: ['https://services.tanssi-testnet.network/dancelight-2001'],
webSocket: ['wss://services.tanssi-testnet.network/dancelight-2001'],
},
public: {
http: ['https://services.tanssi-testnet.network/dancelight-2001'],
webSocket: ['wss://services.tanssi-testnet.network/dancelight-2001'],
},
},
blockExplorers: {
default: {
name: 'Explorer',
url: 'https://dancelight-2001-blockscout.tanssi-chains.network/',
},
},
});
// 3. Create a public client for reading chain data
const rpcUrl = 'https://services.tanssi-testnet.network/dancelight-2001';
const publicClient = createPublicClient({
chain: demoEVM,
transport: http(rpcUrl),
});
// 4. Create address variables
const addressFrom = 'INSERT_ADDRESS_FROM';
const addressTo = 'INSERT_ADDRESS_TO';
// 5. Create balances function
const balances = async () => {
// 6. Fetch balances
const balanceFrom = formatEther(
await publicClient.getBalance({ address: addressFrom })
);
const balanceTo = formatEther(
await publicClient.getBalance({ address: addressTo })
);
console.log(`The balance of ${addressFrom} is: ${balanceFrom} TANGO`);
console.log(`The balance of ${addressTo} is: ${balanceTo} TANGO`);
};
// 7. Call the balances function
balances();
Execute:
npx ts-node balances.ts
Saldos em TANGO serão exibidos.
Script de envio¶
Crie o arquivo:
touch transaction.ts
Passos:
- Importe
createPublicClient,createWalletClient,http,parseEther,defineChaineprivateKeyToAccount. - Defina a cadeia (inclua URLs
public/default). - Configure o cliente de carteira (escrita) com sua chave (não salve chaves reais em TS).
- Configure o cliente público (leitura) para aguardar recibo.
- Defina
addressTo. - Crie
send()com o objeto da transação. - Envie com
walletClient.sendTransactione aguarde o hash. - Aguarde o recibo com
publicClient.waitForTransactionReceipt. - Chame
send().
Ver transaction.ts
// 1. Import the necessary components from viem and viem/accounts
import {
createPublicClient,
createWalletClient,
http,
parseEther,
defineChain,
} from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
// 2. Specify the details of your EVM network
export const demoEVM = defineChain({
id: 5678,
name: 'demo',
network: 'demo',
nativeCurrency: {
decimals: 18,
name: 'TANGO',
symbol: 'TANGO',
},
rpcUrls: {
default: {
http: ['https://services.tanssi-testnet.network/dancelight-2001'],
webSocket: ['wss://services.tanssi-testnet.network/dancelight-2001'],
},
public: {
http: ['https://services.tanssi-testnet.network/dancelight-2001'],
webSocket: ['wss://services.tanssi-testnet.network/dancelight-2001'],
},
},
blockExplorers: {
default: {
name: 'Explorer',
url: 'https://dancelight-2001-blockscout.tanssi-chains.network/',
},
},
});
// 3. Create a wallet client for writing chain data
// The private key must be prepended with `0x` to avoid errors
const account = privateKeyToAccount('INSERT_PRIVATE_KEY');
const rpcUrl = 'https://services.tanssi-testnet.network/dancelight-2001';
const walletClient = createWalletClient({
account,
chain: demoEVM,
transport: http(rpcUrl),
});
// 4. Create a public client for reading chain data
const publicClient = createPublicClient({
chain: demoEVM,
transport: http(rpcUrl),
});
// 5. Create to address variable
const addressTo = 'INSERT_ADDRESS_TO';
// 6. Create send function
const send = async () => {
console.log(
`Attempting to send transaction from ${account.address} to ${addressTo}`
);
// 7. Sign and send transaction
const hash = await walletClient.sendTransaction({
to: addressTo,
value: parseEther('1'),
});
// 8. Wait for the transaction receipt
await publicClient.waitForTransactionReceipt({
hash,
});
console.log(`Transaction successful with hash: ${hash}`);
};
// 9. Call the send function
send();
Execute:
npx ts-node transaction.ts
Você verá o hash; use balances.ts antes/depois para confirmar saldos.
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 em TypeScript que usa o compilador Solidity para gerar o bytecode e a interface (ABI) do contrato Incrementer.sol. Para começar, crie o arquivo compile.ts executando:
touch compile.ts
Depois, escreva o script seguindo 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 com
solc.compileusando o objetoinput - Extraia o contrato compilado e exporte-o para ser usado no script de implantação
// 1. Import packages
const fs = require('fs');
const solc = require('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 crie deploy.ts:
touch deploy.ts
Passos:
- Importe
createPublicClient,createWalletClient,http,defineChain,privateKeyToAccounte ocontractFiledecompile.ts. - Defina a cadeia (inclua URLs
public/default). - Configure o cliente de carteira (escrita) para implantar (não salve chaves reais em TS).
- Configure o cliente público (leitura) para obter recibo.
- Carregue
bytecodeeabi. - Crie a função
deploy. - Use
walletClient.deployContractcom ABI, bytecode, conta e valor inicial. - Aguarde recibo/leitura conforme necessário.
- Chame
deploy().
Ver deploy.ts
// 1. Update import
import {
createPublicClient,
createWalletClient,
http,
defineChain,
} from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import contractFile from './compile';
// 2. Specify the details of your EVM network
export const demoEVM = defineChain({
id: 5678,
name: 'demo',
network: 'demo',
nativeCurrency: {
decimals: 18,
name: 'TANGO',
symbol: 'TANGO',
},
rpcUrls: {
default: {
http: ['https://services.tanssi-testnet.network/dancelight-2001'],
webSocket: ['wss://services.tanssi-testnet.network/dancelight-2001'],
},
public: {
http: ['https://services.tanssi-testnet.network/dancelight-2001'],
webSocket: ['wss://services.tanssi-testnet.network/dancelight-2001'],
},
},
blockExplorers: {
default: {
name: 'Explorer',
url: 'https://dancelight-2001-blockscout.tanssi-chains.network/',
},
},
});
// 3. Create a wallet client for writing chain data
// The private key must be prepended with `0x` to avoid errors
const account = privateKeyToAccount('INSERT_PRIVATE_KEY');
const rpcUrl = 'https://services.tanssi-testnet.network/dancelight-2001';
const walletClient = createWalletClient({
account,
chain: demoEVM,
transport: http(rpcUrl),
});
// 4. Create a public client for reading chain data
const publicClient = createPublicClient({
chain: demoEVM,
transport: http(rpcUrl),
});
// 5. Load contract information
const bytecode = contractFile.evm.bytecode.object;
const abi = contractFile.abi;
const _initialNumber = 5;
// 6. Create deploy function
const deploy = async () => {
console.log(`Attempting to deploy from account: ${account.address}`);
// 7. Send transaction (initial value set to 5)
const contract = await walletClient.deployContract({
abi,
account,
bytecode,
args: [_initialNumber],
});
// 8. Get the transaction receipt for the deployment
const transaction = await publicClient.waitForTransactionReceipt({
hash: contract,
});
console.log(`Contract deployed at address: ${transaction.contractAddress}`);
};
// 9. Call the deploy function
deploy();
Execute:
npx ts-node deploy.ts
O endereço do contrato será exibido.
Ler dados do contrato (calls)¶
Calls não alteram estado; não precisam de transação. Crie get.ts:
touch get.ts
Passos:
- Importe
createPublicClient,http,defineChainecontractFiledecompile.ts. - Defina a cadeia (inclua URLs
public/default). - Configure o cliente público.
- Defina
contractAddresseabi. - Crie a função
get. - Chame
publicClient.readContract(funçãonumber) e exiba o valor. - Chame
get().
Ver get.ts
// 1. Update import
import { createPublicClient, http, defineChain } from 'viem';
import contractFile from './compile';
// 2. Specify the details of your EVM network
export const demoEVM = defineChain({
id: 5678,
name: 'demo',
network: 'demo',
nativeCurrency: {
decimals: 18,
name: 'TANGO',
symbol: 'TANGO',
},
rpcUrls: {
default: {
http: ['https://services.tanssi-testnet.network/dancelight-2001'],
webSocket: ['wss://services.tanssi-testnet.network/dancelight-2001'],
},
public: {
http: ['https://services.tanssi-testnet.network/dancelight-2001'],
webSocket: ['wss://services.tanssi-testnet.network/dancelight-2001'],
},
},
blockExplorers: {
default: {
name: 'Explorer',
url: 'https://dancelight-2001-blockscout.tanssi-chains.network/',
},
},
});
// 3. Create a public client for reading chain data
const rpcUrl = 'https://services.tanssi-testnet.network/dancelight-2001';
const publicClient = createPublicClient({
chain: demoEVM,
transport: http(rpcUrl),
});
// 4. Create contract variables
const contractAddress = 'INSERT_CONTRACT_ADDRESS';
const abi = contractFile.abi;
// 5. Create get function
const get = async () => {
console.log(`Making a call to contract at address: ${contractAddress}`);
// 6. Call contract
const data = await publicClient.readContract({
abi,
functionName: 'number',
address: contractAddress,
args: [],
});
console.log(`The current number stored is: ${data}`);
};
// 7. Call get function
get();
Execute:
npx ts-node get.ts
Interagir com o contrato (sends)¶
Sends alteram estado e exigem transação. Crie increment.ts e reset.ts:
touch increment.ts reset.ts
increment.ts:
- Importe
createPublicClient,createWalletClient,http,defineChain,privateKeyToAccountecontractFile. - Defina a cadeia (inclua URLs
public/default). - Configure o cliente de carteira (escrita) (não salve chaves reais em TS).
- Configure o cliente público (leitura) para recibo.
- Defina
contractAddress,abi,_value. - Crie
increment(). - Chame
walletClient.writeContractcom_valuee aguarde hash. - Aguarde recibo com
publicClient.waitForTransactionReceipt. - Chame
increment().
Ver increment.ts
// 1. Update import
import {
createPublicClient,
createWalletClient,
http,
defineChain,
} from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import contractFile from './compile';
// 2. Specify the details of your EVM network
export const demoEVM = defineChain({
id: 5678,
name: 'demo',
network: 'demo',
nativeCurrency: {
decimals: 18,
name: 'TANGO',
symbol: 'TANGO',
},
rpcUrls: {
default: {
http: ['https://services.tanssi-testnet.network/dancelight-2001'],
webSocket: ['wss://services.tanssi-testnet.network/dancelight-2001'],
},
public: {
http: ['https://services.tanssi-testnet.network/dancelight-2001'],
webSocket: ['wss://services.tanssi-testnet.network/dancelight-2001'],
},
},
blockExplorers: {
default: {
name: 'Explorer',
url: 'https://dancelight-2001-blockscout.tanssi-chains.network/',
},
},
});
// 3. Create a wallet client for writing chain data
// The private key must be prepended with `0x` to avoid errors
const account = privateKeyToAccount('INSERT_PRIVATE_KEY');
const rpcUrl = 'https://services.tanssi-testnet.network/dancelight-2001';
const walletClient = createWalletClient({
account,
chain: demoEVM,
transport: http(rpcUrl),
});
// 4. Create a public client for reading chain data
const publicClient = createPublicClient({
chain: demoEVM,
transport: http(rpcUrl),
});
// 5. Create contract variables
const contractAddress = 'INSERT_CONTRACT_ADDRESS';
const abi = contractFile.abi;
const _value = 3;
// 6. Create increment function
const increment = async () => {
console.log(
`Calling the increment by ${_value} function in contract at address: ${contractAddress}`
);
// 7. Call contract
const hash = await walletClient.writeContract({
abi,
functionName: 'increment',
address: contractAddress,
args: [_value],
});
// 8. Wait for the transaction receipt
await publicClient.waitForTransactionReceipt({
hash,
});
console.log(`Transaction successful with hash: ${hash}`);
};
// 9. Call increment function
increment();
Execute:
npx ts-node increment.ts
reset.ts:
- Importe as mesmas dependências de
increment.ts. - Defina a cadeia.
- Configure clientes de carteira e público.
- Defina
contractAddresseabi. - Crie
reset(). - Chame
walletClient.writeContract(funçãoreset) e aguarde hash. - Aguarde recibo com
publicClient.waitForTransactionReceipt. - Chame
reset().
Ver reset.ts
// 1. Update import
import {
createPublicClient,
createWalletClient,
http,
defineChain,
} from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import contractFile from './compile';
// 2. Specify the details of your EVM network
export const demoEVM = defineChain({
id: 5678,
name: 'demo',
network: 'demo',
nativeCurrency: {
decimals: 18,
name: 'TANGO',
symbol: 'TANGO',
},
rpcUrls: {
default: {
http: ['https://services.tanssi-testnet.network/dancelight-2001'],
webSocket: ['wss://services.tanssi-testnet.network/dancelight-2001'],
},
public: {
http: ['https://services.tanssi-testnet.network/dancelight-2001'],
webSocket: ['wss://services.tanssi-testnet.network/dancelight-2001'],
},
},
blockExplorers: {
default: {
name: 'Explorer',
url: 'https://dancelight-2001-blockscout.tanssi-chains.network/',
},
},
});
// 3. Create a wallet client for writing chain data
// The private key must be prepended with `0x` to avoid errors
const account = privateKeyToAccount('INSERT_PRIVATE_KEY');
const rpcUrl = 'https://services.tanssi-testnet.network/dancelight-2001';
const walletClient = createWalletClient({
account,
chain: demoEVM,
transport: http(rpcUrl),
});
// 4. Create a public client for reading chain data
const publicClient = createPublicClient({
chain: demoEVM,
transport: http(rpcUrl),
});
// 5. Create contract variables
const contractAddress = 'INSERT_CONTRACT_ADDRESS';
const abi = contractFile.abi;
// 6. Create reset function
const reset = async () => {
console.log(
`Calling the reset function in contract at address: ${contractAddress}`
);
// 7. Call contract
const hash = await walletClient.writeContract({
abi,
functionName: 'reset',
address: contractAddress,
args: [],
});
// 8. Wait for the transaction receipt
await publicClient.waitForTransactionReceipt({
hash,
});
console.log(`Transaction successful with hash: ${hash}`);
};
// 9. Call reset function
reset();
Execute:
npx ts-node reset.ts
| Criada: 9 de dezembro de 2025





