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.
Top comments (0)