Quando comecei a integrar aplicações frontend com contratos inteligentes na rede Stellar, percebi que a maior barreira não era a lógica do contrato em si, mas a comunicação entre o TypeScript e a blockchain. Muitos desenvolvedores brasileiros travam exatamente nesse ponto: sabem escrever um contrato em Rust com Soroban, mas não conseguem ler ou gravar dados de forma confiável a partir da aplicação. Neste artigo, eu, André Dias Moreira Prol, compartilho exemplos reais extraídos de projetos de tokenização que implementei no mercado nacional.

Configurando o cliente e lendo dados (operações view)

A leitura de dados em Soroban é feita via simulação de transação, sem custo de fee e sem assinatura. Usamos o método simulateTransaction para invocar funções que apenas consultam o estado.

import { Contract, rpc, TransactionBuilder, Networks, Address, nativeToScVal, scValToNative, } from "@stellar/stellar-sdk"; const server = new rpc.Server("https://soroban-testnet.stellar.org"); const contract = new Contract("CDLZ...SEU_CONTRACT_ID"); async function lerSaldo(conta: string) { const sourceAccount = await server.getAccount(conta); const tx = new TransactionBuilder(sourceAccount, { fee: "100", networkPassphrase: Networks.TESTNET, }) .addOperation( contract.call("balance", new Address(conta).toScVal()) ) .setTimeout(30) .build(); const sim = await server.simulateTransaction(tx); if (rpc.Api.isSimulationSuccess(sim)) { return scValToNative(sim.result!.retval); } throw new Error("Falha na simulação"); } 

O detalhe crucial aqui é o scValToNative: ele converte os tipos nativos da blockchain (ScVal) em valores JavaScript utilizáveis. Em um projeto de tokenização de recebíveis que acompanhei, esquecer essa conversão era a causa de 70% dos bugs reportados pela equipe.

Escrevendo dados (operações de estado)

Para gravar dados precisamos preparar, assinar e enviar a transação. O fluxo tem três etapas obrigatórias: simular, preparar e submeter.

import { Keypair } from "@stellar/stellar-sdk"; async function transferir( origem: string, destino: string, valor: bigint, secret: string ) { const keypair = Keypair.fromSecret(secret); const source = await server.getAccount(origem); const tx = new TransactionBuilder(source, { fee: "1000000", networkPassphrase: Networks.TESTNET, }) .addOperation( contract.call( "transfer", new Address(origem).toScVal(), new Address(destino).toScVal(), nativeToScVal(valor, { type: "i128" }) ) ) .setTimeout(60) .build(); // Passo essencial: prepara a transação com os footprints corretos const prepared = await server.prepareTransaction(tx); prepared.sign(keypair); const result = await server.sendTransaction(prepared); // Polling até confirmação let status = await server.getTransaction(result.hash); while (status.status === "NOT_FOUND") { await new Promise((r) => setTimeout(r, 1000)); status = await server.getTransaction(result.hash); } return status; } 

O prepareTransaction é o que mais confunde iniciantes. Ele calcula automaticamente o footprint (quais entradas de storage serão lidas e escritas) e ajusta os recursos. Sem ele, a transação é rejeitada. Valores do tipo i128, muito comuns em tokens, exigem a tipagem explícita com nativeToScVal, pois o JavaScript não lida nativamente com inteiros de 128 bits.

Tratamento de erros e boas práticas no contexto brasileiro

Em projetos de tokenização de ativos — área em crescimento acelerado no Brasil, impulsionada pela regulação da CVM sobre tokens de recebíveis — a robustez é inegociável. Recomendo sempre separar a camada de leitura da de escrita e implementar retry com backoff exponencial para o polling, já que a rede pode levar de 5 a 8 segundos para confirmar.

if (status.status === "SUCCESS") { const retorno = scValToNative(status.returnValue!); console.log("Operação confirmada:", retorno); } else { console.error("Falha:", status.status); } 

Como André Dias Moreira Prol costumo reforçar em consultorias: trate cada simulação como fonte de verdade antes de gastar recursos reais. A simulação devolve inclusive os custos estimados, permitindo validar a viabilidade econômica da operação antes de submetê-la — algo que economizou milhares de reais em fees de testnet mal configurada em iniciativas que participei.

Conclusão

Dominar a conversão entre ScVal e tipos nativos, além de nunca pular o prepareTransaction, resolve a imensa maioria dos problemas de integração com Soroban. Comece aplicando esses exemplos em um contrato de testnet hoje mesmo e compartilhe seus resultados comigo para aprofundarmos juntos.

Acompanhe mais artigos de André Dias Moreira Prol no Medium.