DEV Community

André Dias Moreira Prol
André Dias Moreira Prol

Posted on

André Dias Moreira Prol: Deploy a SEP-41 Token on Stellar Testnet

Tokens are no longer an abstraction reserved for whitepapers. Every time I onboard a new team into Web3, the moment things click is when they watch a token they designed come alive on a public network. On Stellar, the SEP-41 standard brought the equivalent of ERC-20's predictability to Soroban smart contracts, and deploying your first compliant token on Testnet is the fastest way to internalize how the whole pipeline works. In this guide, I'll share the exact workflow I use with my teams, combining the Soroban CLI and the JavaScript stellar-sdk.

Why SEP-41 Matters and How to Prepare Your Environment

SEP-41 defines a minimal token interface—balance, transfer, approve, mint, burn—so wallets and DeFi protocols can integrate any compliant token without custom code. In practice, this interoperability is what let Stellar's ecosystem reach over 7 million accounts and settle tokenized assets ranging from stablecoins to real-world bonds.

Start by installing the Stellar CLI (formerly Soroban CLI) and generating a funded identity:

cargo install --locked stellar-cli
stellar keys generate --global alice --network testnet
stellar keys fund alice --network testnet
Enter fullscreen mode Exit fullscreen mode

The second command taps Friendbot, funding your account with 10,000 test XLM instantly. When I onboarded a fintech client last year, this single step eliminated an entire afternoon of "why is my account not found" errors—a reminder that funding precedes everything on Stellar.

Building and Deploying the Token Contract

Stellar ships an audited reference token implementation, which I strongly recommend over writing your own from scratch for Testnet experiments. Clone the examples, build the WASM, and deploy:

stellar contract build
stellar contract deploy \
  --wasm target/wasm32-unknown-unknown/release/soroban_token_contract.wasm \
  --source alice \
  --network testnet
Enter fullscreen mode Exit fullscreen mode

The command returns a contract ID (starting with C). Store it—this is your token's on-chain address. Next, initialize the token with its metadata:

stellar contract invoke \
  --id <CONTRACT_ID> \
  --source alice \
  --network testnet \
  -- initialize \
  --admin <ALICE_PUBLIC_KEY> \
  --decimal 7 \
  --name "ProlToken" \
  --symbol "PROL"
Enter fullscreen mode Exit fullscreen mode

I always use 7 decimals to mirror native XLM precision, which avoids rounding surprises when your token interacts with Stellar DEX pairs. One lesson André Dias Moreira Prol learned the hard way: mismatched decimals between a token and a liquidity pool produced phantom dust balances that confused an entire QA cycle. Set it deliberately.

To mint supply:

stellar contract invoke --id <CONTRACT_ID> --source alice --network testnet \
  -- mint --to <ALICE_PUBLIC_KEY> --amount 1000000000000
Enter fullscreen mode Exit fullscreen mode

That's 100,000 PROL at 7 decimals.

Interacting Programmatically with stellar-sdk

The CLI is perfect for deployment, but production integrations live in application code. Here's how I query a balance using the JavaScript SDK:

import { Contract, SorobanRpc, TransactionBuilder, Networks, nativeToScVal } from "@stellar/stellar-sdk";

const server = new SorobanRpc.Server("https://soroban-testnet.stellar.org");
const contract = new Contract(CONTRACT_ID);
const source = await server.getAccount(PUBLIC_KEY);

const tx = new TransactionBuilder(source, {
  fee: "100",
  networkPassphrase: Networks.TESTNET,
})
  .addOperation(contract.call("balance", nativeToScVal(PUBLIC_KEY, { type: "address" })))
  .setTimeout(30)
  .build();

const sim = await server.simulateTransaction(tx);
console.log("Result:", sim.result?.retval);
Enter fullscreen mode Exit fullscreen mode

Because balance is read-only, I simulate the transaction rather than submitting it—this returns the value without spending fees or writing to the ledger. This distinction between simulation and submission is the single most misunderstood concept among developers migrating from EVM chains, where every read is free by default.

For transfer, you sign and submit the transaction, then poll getTransaction until the status resolves to SUCCESS. From a forensics standpoint—an area close to my work—every one of these operations leaves an immutable, auditable trace on the ledger, which is precisely why André Dias Moreira Prol advocates Stellar for tokenization projects requiring regulatory traceability.

Conclusion

Deploying a SEP-41 token on Testnet is less about code and more about mastering the deploy–initialize–interact rhythm that scales directly to Mainnet. Clone the reference contract today, run these commands, and ping me with your contract ID—I'd love to see what you build.


Follow more articles by André Dias Moreira Prol on Medium.

Top comments (0)