Getting Started
Run Shade end-to-end on Stellar testnet: prerequisites, install, generating and funding testnet keys, deploying the Soroban contract, and your first commands.
Run Shade end-to-end on Stellar testnet in a few minutes. This page covers prerequisites, install, generating and funding testnet keys, deploying the contract, and your first commands.
Prerequisites
- Node.js 20+ — all you need to install and run the CLI.
- Stellar CLI and a Rust toolchain — only needed to build/deploy the Soroban pool contract yourself, and to generate/fund testnet keys via
stellar keys.
Install the CLI
The shade command ships on npm as stellar-shade-cli:
npm install -g stellar-shade-cliThat is everything the account method needs. The pool method additionally needs a deployed pool contract; to deploy your own (below), clone the repo and build:
npm install
# Build every TypeScript package
npm run build
# Build the Soroban contract
cd contracts && stellar contract build && cd ..Generate and fund a testnet account
Generate a keypair and fund it from friendbot. Repeat for any accounts you need: a deployer, a sender, a fee payer.
stellar keys generate deployer --network testnet
stellar keys fund deployer --network testnetDeploying the contract
bash contracts/deploy.sh --network testnet --source deployerThe script builds the contract, deploys it to testnet, and writes the resulting contract id to ~/.stealth/testnet-contract, where the CLI will find it.
How the CLI resolves the contract address: it reads ~/.stealth/<network>-contract. There is deliberately no built-in testnet address. Testnet resets periodically, and a stale placeholder would only produce an opaque Soroban failure later. If the file is missing, the CLI throws an actionable error naming the exact file to write, and the SDK throws ContractIdRequiredError.
If you prefer to deploy by hand instead of the script:
stellar contract deploy \
--wasm contracts/registry/target/wasm32-unknown-unknown/release/stealth_registry.wasm \
--source deployer --network testnet
# then save it where the CLI looks:
echo "C..." > ~/.stealth/testnet-contractYour first commands
# 1. Generate keys. The keystore is ENCRYPTED by default (AES-256-GCM).
# --mnemonic gives you a 12-word backup phrase.
shade keygen --mnemonic
# prints your meta-address: shade:stellar:...
# 2. Send. A delivery method is REQUIRED. There is no implicit default.
# Supply the secret via $SHADE_FROM_SECRET or the prompt, never a flag.
export SHADE_FROM_SECRET=S...
shade send <meta-address> 100 --method pool --network testnet
# 3. Find what you received
shade scan --network testnet
shade balance --network testnet
# 4. Claim to your real address
export SHADE_FEE_PAYER=S...
shade claim <stealth-address> <your-G-address> --network testnetSecrets never belong on the command line
--from and --fee-payer exist for scripting, but a flag leaks into shell history and ps output. Prefer SHADE_FROM_SECRET, SHADE_FEE_PAYER, or the stderr prompt.
Running the relayer (optional)
The relayer pays your withdrawal fee so you never reveal a funded account of your own:
RELAYER_SECRET=S... npx tsx packages/relayer/src/index.ts
# or, from the repo root:
npm run relayer:devThen pass --relay http://localhost:3000 to claim/withdraw. See Relayer for endpoints, credit gating, and deployment.
Running the indexer (optional)
The announcement indexer makes account-method discovery fast. It walks the global Horizon transaction feed once for everyone, so a cold scan no longer has to:
cd packages/indexer && npm run dev # NETWORK=testnet, port 3100Then pass --indexer http://localhost:3100 to scan/balance (or set SHADE_INDEXER). Horizon remains the source of truth: a scan falls back to the plain Horizon walk automatically if the indexer is down. See Architecture → The announcement indexer for the trust model, endpoints, and configuration.
Using the SDK instead
import { StealthClient } from 'stellar-shade';
const client = new StealthClient({
network: 'testnet',
contractId: 'C...', // required whenever 'pool' is enabled
methods: ['pool', 'account'],
});
const bob = StealthClient.keygen(); // share bob.metaAddress
await client.send(bob.metaAddress, 100, aliceSecret, { method: 'auto' });
const payments = await client.scan(bob);
await client.claim(payments[0], bobPublicKey, {
keys: bob,
feePayer: feePayerSecret,
});Full API in the SDK Reference.
Tests
npm run test # all TypeScript packages, then cargo test
cd contracts && cargo test # Rust contract tests onlyNetworks
| Network | Passphrase | RPC | Horizon |
|---|---|---|---|
testnet | Testnet | https://soroban-testnet.stellar.org | https://horizon-testnet.stellar.org |
testnet is the only accepted network today. Mainnet (“public”) is a forward-looking, post-audit addition.
Status note
The pool method works with native XLM and is asset-agnostic: it calls the standard SAC token interface (token::Client) with the token address as a parameter, so a classic asset such as USDC takes the identical path with a different address. No testnet contract id is pinned, because testnet resets, so deploy your own and save it. The account method’s cold discovery is served by the announcement indexer; every scan ends with a Horizon tail, so an unreachable indexer falls back to the plain walk. Without an indexer configured, a cold account scan walks the global Horizon transaction feed, which is impractical for a fresh recipient on a busy network. Mainnet is out of scope until an external audit lands. See Security.
Next steps
- CLI Reference: every command and flag
- SDK Reference:
StealthClient, types, errors - Delivery Methods: choosing
poolvsaccount - FAQ & Troubleshooting: when something fails
Delivery Methods
Compare Shade's delivery methods: the Soroban pool contract versus a direct one-time Stellar account. Where funds sit, what they cost, and how you claim them.
CLI Reference
Every shade CLI command and flag: keygen, address, send, scan, balance, claim and withdraw, plus secret handling and the encrypted keystore format.