Skip to content
Testnet only: a reference implementation, not a production service.Tokens and bank transfers here are simulated and have no value.

Run it locally

This is the local path from the README: run the stack in containers, generate the Platform keys, bootstrap the asset on Testnet, then point the app at it. You need git, Docker and curl; everything else runs in containers. Fill in every <PLACEHOLDER> yourself and keep secrets out of git.

1. Run the stack

Copy the example environment, start Postgres, and build the core image.

cp .env.example .env
docker compose up -d postgres
docker compose build core

Generate four Testnet keypairs: the issuer, the distribution account, the sponsor, and the wallet you will mint to. The wallet secret stays in your shell, not in .env.

docker compose run --rm --no-deps core node --input-type=module -e '
import { Keypair } from "@stellar/stellar-sdk";
for (const n of ["ISSUER", "DISTRIBUTION", "SPONSOR", "WALLET"]) {
  const k = Keypair.random();
  console.log(`${n}_SECRET=${k.secret()}\n${n}_ADDRESS=${k.publicKey()}`);
}'

Fill .env with those addresses and secrets, a signing secret, and the database URL. The chain watcher stays off without WATCH_START_LEDGER, and without it the mint never completes.

ISSUER_SECRET=<ISSUER_SECRET>
DISTRIBUTION_SECRET=<DISTRIBUTION_SECRET>
SPONSOR_SECRET=<SPONSOR_SECRET>
ASSET_ISSUER=<ISSUER_ADDRESS>
DISTRIBUTION_ADDRESS=<DISTRIBUTION_ADDRESS>
SPONSOR_ADDRESS=<SPONSOR_ADDRESS>
SIGNER_SHARED_SECRET=<any long random string>
BANK_WEBHOOK_SECRET=<any long random string>
HOME_DOMAIN=issuer.example
DATABASE_URL=postgres://postgres:postgres@localhost:5432/stablecoin
BANK_WEBHOOK_URL=http://core:4000/internal/bank/webhook
WATCH_START_LEDGER=<latest ledger, from the call below>

Read the latest ledger from the RPC and use the sequence it returns for WATCH_START_LEDGER. Then create the database tables.

curl -s https://soroban-testnet.stellar.org -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"getLatestLedger"}'

docker compose run --rm --no-deps core pnpm migrate

2. Bootstrap Testnet

The bootstrap needs a signer in bootstrap mode, which the stack's own signer never runs in, so this one-off container starts a temporary signer beside the bootstrap command. --seed also resets and seeds the off-chain ledger (destructive; Testnet only). It funds the accounts through Friendbot, which can take a few minutes; if it reports a connection error, run it again.

docker compose run --rm -e BOOTSTRAP_MODE=1 -e DATABASE_ADMIN_URL=postgres://postgres:postgres@postgres:5432/stablecoin signer bash -c 'pnpm --filter @scr/signer start & for i in {1..30}; do (echo > /dev/tcp/localhost/4100) 2>/dev/null && break; sleep 1; done; pnpm --filter @scr/bootstrap bootstrap --seed'

It prints SAC <contract id> at the end. Put that in .env as ASSET_CONTRACT=<SAC id>, then start everything.

docker compose up -d

The stack is now running locally. The Quickstart continues from a hosted Testnet API key against an issuer like this one.

Edit on GitHub