From Zero to Testnet
This tutorial takes a new Caatinga project from scaffold to a deployed Soroban counter contract on Stellar testnet.
Install @caatinga/cli, @caatinga/core, @caatinga/client, and @caatinga/zk from npm. Pin @next or an exact version for reproducible installs.
Prerequisites
Install Node.js 22+ and Rust first. Then install the supported Stellar CLI and Wasm target:
npm install -g @caatinga/cli@next
cargo install --locked stellar-cli --version 25.2.0
rustup target add wasm32v1-none
stellar --version
rustc --versionCreate and fund a local Stellar CLI identity:
stellar keys generate alice --fund --network testnet--source must be a local Stellar CLI identity, not a public G... address. Caatinga rejects public addresses for deploy/invoke because those operations need a signer.
Create the Project
caatinga init my-dapp
cd my-dapp
npm installpnpm install also works. The default react-vite-counter template includes pnpm-workspace.yaml for pnpm 10.26+/11.x (see Templates).
Without a global CLI install, run npx caatinga@next init my-dapp instead of caatinga init.
The default template creates:
caatinga.config.tswith contracts, output paths, and networks.caatinga.artifacts.jsonfor per-network deployed contract IDs.contracts/with Rust Soroban contract source.src/with frontend/client code.
Verify the Environment
npx caatinga doctor --network testnet --source aliceExpected shape:
Caatinga Doctor
✓ Node.js 22
✓ Stellar CLI 25.2.0
✓ Rust 1.84.0
✓ wasm32v1-none target installed
✓ caatinga.config.ts found
✓ caatinga.artifacts.json found
✓ network testnet found
✓ source identity alice found
Status: readyIf caatinga doctor reports ✓ Stellar CLI 26.0.0 (1 warning) followed by a STELLAR_CLI_UNTESTED_VERSION bullet, the command is still ready — that warning is advisory and does not block deploys, generates, or invokes. See the Stellar CLI version contract for the warning semantics.
If Stellar CLI is missing, install it:
cargo install --locked stellar-cli --version 25.2.0If the Wasm target is missing, install it:
rustup target add wasm32v1-noneBuild, Deploy, Invoke
npx caatinga build counter
npx caatinga deploy counter --network testnet --source alice
npx caatinga invoke counter.increment --network testnet --source alicedeploy saves the deployed contractId under the selected network in caatinga.artifacts.json and then generates TypeScript bindings automatically under the bindings directory configured in caatinga.config.ts. Pass --no-generate to skip generation; if generation fails the deploy still succeeds and the CLI prints the recovery command (npx caatinga generate --network testnet).
Check the result at any time:
npx caatinga status --network testnetThe table shows each contract's contract ID, whether it is deployed, and whether its bindings are still fresh (a redeploy marks them stale until the next generate).
To redeploy even when an artifact already contains a contract ID:
npx caatinga deploy counter --network testnet --source alice --forceUse the Contract in a Client
After deploy (which generated the bindings), install the browser packages:
npm install @caatinga/client @caatinga/core @creit.tech/stellar-wallets-kitBrowser code can compose artifacts, generated bindings, network config, and a wallet adapter (single-invoker only until v1.0 — see Client scope):
import { createCaatingaClient } from "@caatinga/client";
import { createStellarWalletsKitAdapter } from "@caatinga/client/stellar-wallets-kit";
import * as Counter from "./contracts/generated/counter";
import artifacts from "../caatinga.artifacts.json";
const client = createCaatingaClient({
network: {
name: "testnet",
rpcUrl: "https://soroban-testnet.stellar.org",
networkPassphrase: "Test SDF Network ; September 2015",
},
artifacts,
wallet: createStellarWalletsKitAdapter(),
contracts: { counter: { binding: Counter } },
});
const before = await client.contract("counter").read<number>("get");
const increment = await client.contract("counter").invoke<number>("increment");For the full client contract, XDR debug options, and wallet adapter rules, see Client. For wallet sessions, persistence, and the React WalletProvider/useWallet hooks used by the default template, see Wallets.
Troubleshooting
ERR_PNPM_IGNORED_BUILDS(esbuild): pnpm 11 blocks lifecycle scripts by default. Ensurepnpm-workspace.yamlcontainsallowBuilds.esbuild: true(already in the officialreact-vite-countertemplate). If you ranpnpm approve-buildsinteractively, replace any placeholder value with the booleantrue— incomplete approval leaves invalid YAML.- Deprecated
uuidwarnings on install: the officialreact-vite-countertemplate pinsuuid@^14viapackage.jsonoverrides. Regenerate from a current template or add the same override if you created the project before this change. - Deprecated
@safe-global/safe-gateway-typescript-sdkon install: optional Safe packages from Reown AppKit (via Stellar Wallets Kit). The official template blocks them with npm/pnpm overrides — regenerate from a current template or copy the Safe override block from Templates. npm auditreports ~14 high vulnerabilities after install: the usual cause is transitivews@<8.21.0via@creit.tech/stellar-wallets-kit→ Reown AppKit →viem(GHSA-96hv-2xvq-fx4p), not Trezor. Official templates pin"ws": "^8.21.0"in npm/pnpm overrides. Regenerate from a current template or copy the override block from Templates — Install override contract. Verify withnpm install && npm audit.npm auditreports criticalprotobufjsfindings: Trezor Connect was not stubbed. Official templates replace@trezor/connect-webwith local stubs undersrc/stubs/— Caatinga does not support hardware wallets yet. See the same override contract.CAATINGA_ARTIFACT_NOT_FOUNDon deploy: WASM was not built yet. Runnpx caatinga build <contract>beforedeploy. After a successful build, ensurecaatinga.config.tspoints totarget/wasm32v1-none/release/*.wasm. Caatinga0.2.2+resolves legacywasm32-unknown-unknownpaths automatically. If you haveCARGO_TARGET_DIRset, Stellar CLI writes the Wasm under that directory instead ofcontracts/<name>/target. Caatinga2.4.1+resolves the Wasm fromCARGO_TARGET_DIRautomatically, but if it still fails, unsetCARGO_TARGET_DIRor update thewasmpath incaatinga.config.ts.- Partial deploy coverage:
caatinga doctorprints missingcontractIds as an advisory section (exit code stays0when the toolchain is ready). Run thecaatinga deploycommands it suggests before invoke/read on testnet. CAATINGA_STELLAR_CLI_NOT_FOUND: install Stellar CLI and ensurestellaris onPATH.CAATINGA_UNSUPPORTED_CLI_VERSION: install Stellar CLI 23.0.0 or newer (25.2.0 recommended). Versions newer than the last-tested 25.2.0 run with a non-fatal stderr advisory; no override flag is required.CAATINGA_RUST_TARGET_NOT_FOUND: runrustup target add wasm32v1-none.CAATINGA_NETWORK_NOT_FOUND: add the network tocaatinga.config.tsor pass a configured--network.CAATINGA_UNSAFE_SOURCE_ACCOUNT: pass a local Stellar CLI identity such asalice, not a publicG...address or secret.