This guide covers everything you need to get a productive VS Code environment for QuorumProof — Rust/Soroban contract development, TypeScript API server, and the React frontend — all in one workspace.
- Prerequisites
- Recommended Extensions
- Opening the Workspace
- Debug Configurations
- Tasks
- Rust-Analyzer Tips
- Common Issues and Fixes
Install the following before opening the project:
| Tool | Minimum Version | Install |
|---|---|---|
| Rust | 1.70 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh |
| wasm32 target | — | rustup target add wasm32-unknown-unknown |
| native debug target | — | rustup target add x86_64-unknown-linux-gnu (Linux) or aarch64-apple-darwin (macOS Apple Silicon) |
| Soroban CLI | latest | cargo install --locked stellar-cli --features opt |
| Node.js | 20 LTS | via nvm or package manager |
| CodeLLDB | — | installed via VS Code extension marketplace (see below) |
The file .vscode/extensions.json lists all recommended extensions. VS Code will
prompt you to install them when you open the workspace. You can also install them
manually from the Extensions panel (Ctrl+Shift+X / ⌘⇧X).
| Extension ID | Purpose |
|---|---|
rust-lang.rust-analyzer |
Rust language server: completions, inlay hints, go-to-definition, inline errors |
serayuzgur.crates |
Shows latest crate versions in Cargo.toml |
tamasfe.even-better-toml |
TOML syntax, formatting, and schema validation |
vadimcn.vscode-lldb |
Native debugger backend for Rust (CodeLLDB) |
ms-vscode.hexeditor |
Inspect WASM binaries in hex |
redhat.vscode-yaml |
YAML language support for CI configs, k8s manifests |
esbenp.prettier-vscode |
Formatter for TypeScript, JSON, Markdown |
dbaeumer.vscode-eslint |
ESLint integration for the API server and frontend |
ms-vscode.vscode-typescript-next |
Nightly TypeScript language features |
usernamehw.errorlens |
Surfaces errors and warnings inline in the editor |
streetsidesoftware.code-spell-checker |
Catches typos in code and documentation |
Open the repository root directly:
File → Open Folder → /path/to/QuorumProof
VS Code will automatically pick up .vscode/settings.json, .vscode/tasks.json,
and .vscode/launch.json.
Debug configurations live in .vscode/launch.json. Open the Run & Debug panel
(Ctrl+Shift+D / ⌘⇧D), pick a configuration from the dropdown, and press F5.
These three configurations use CodeLLDB (vadimcn.vscode-lldb) to compile
and launch the test binary for a specific Soroban contract package.
Important: The cargo.args in each configuration pass
--target x86_64-unknown-linux-gnu (or the equivalent native target for your
machine). Soroban contracts normally compile to wasm32-unknown-unknown, but
debuggers cannot attach to WASM — the native target produces a standard ELF/Mach-O
binary that CodeLLDB can instrument. This is the correct approach for unit tests
because Soroban's soroban-sdk test utilities work on native targets.
Steps:
- Set a breakpoint anywhere in
contracts/<name>/src/. - Select e.g. "Debug Rust Tests (quorum_proof)" in the Run & Debug panel.
- Press F5. VS Code compiles the test binary, then pauses at your breakpoint.
Filtering to a single test:
The args array in the configuration is passed to the compiled test binary.
You can filter by test name:
"args": ["my_test_name"]or to run a specific module:
"args": ["credential_issuance::"]Attach to a running API server process that was started with the --inspect flag.
- Start the server in debug mode:
cd api-server node --inspect ./node_modules/.bin/tsx src/index.ts # or via the "Start API Server" task — edit it to add --inspect if needed
- Select "Debug API Server" in the Run & Debug panel.
- Press F5. VS Code attaches to port 9229.
The configuration has "restart": true, so it reconnects automatically when the
process restarts (e.g. if you use nodemon or tsx --watch).
Launches Vitest in debug mode so you can step through test code.
- Select "Debug Frontend Tests".
- Press F5. Vitest runs with the Node.js debugger enabled.
- Set breakpoints in
frontend/src/orfrontend/src/__tests__/.
Tasks are defined in .vscode/tasks.json and can be run from:
- Terminal → Run Task… menu
Ctrl+Shift+P/⌘⇧P→ "Tasks: Run Task"- Keyboard shortcut:
Ctrl+Shift+Bruns the default build task ("Build Contracts")
| Task | What it does |
|---|---|
| Build Contracts (default build) | Runs scripts/build.sh — compiles all three contracts to wasm32-unknown-unknown |
| Test Contracts (default test) | Runs cargo test across the entire workspace |
| Deploy to Testnet | Runs scripts/deploy_testnet.sh — deploys contracts to Stellar testnet |
| Validate Environment | Runs scripts/validate_env.sh — checks that required env vars and tools are present |
| Start API Server | npm run dev in api-server/ — starts the TypeScript API server with tsx |
| Start Frontend | npm run dev in frontend/ — starts the Vite dev server |
| Run CLI Help | ./cli/qp --help — shows available CLI commands (requires CLI binary from issue #1662) |
Rust tasks ("Build Contracts", "Test Contracts") use the $rustc problem matcher,
so compiler errors appear in VS Code's Problems panel and you can navigate to them
with a click.
The project's .cargo/config.toml sets the default build target to
wasm32-unknown-unknown. .vscode/settings.json propagates this to
rust-analyzer:
"rust-analyzer.cargo.target": "wasm32-unknown-unknown",
"rust-analyzer.cargo.features": "all"This means completions and type-checking reflect the actual WASM build, not a native build. If you see "target not found" errors on first load, run:
rustup target add wasm32-unknown-unknownthen reload the window (Ctrl+Shift+P → "Developer: Reload Window").
rust-analyzer.procMacro.enable is true. The soroban-sdk derives
(#[contractimpl], #[contracttype], etc.) are expanded in the editor, giving
accurate completions and hover docs inside contract functions.
"rust-analyzer.check.command": "check" runs cargo check on every save, which
is much faster than cargo build. Errors appear as squiggles immediately.
The Cargo workspace has five members (quorum_proof, sbt_registry, zk_verifier,
integration_tests, e2e_tests). rust-analyzer loads all of them. If you only
want to work on one contract, you can narrow the scope with:
"rust-analyzer.linkedProjects": [
"contracts/quorum_proof/Cargo.toml"
]Add that to your user settings.json (not the workspace one) so it doesn't
affect other contributors.
Type hints and parameter hints are enabled. Toggle them with Ctrl+Alt+; (Linux/Windows)
or ⌃⌥; (macOS), or via "Rust Analyzer: Toggle Inlay Hints".
rust-analyzer is trying to check against wasm32-unknown-unknown but the target
is not installed.
rustup target add wasm32-unknown-unknownReload the window afterwards.
cargo clean
cargo buildThen reload the window. This rebuilds the proc-macro crates that rust-analyzer shells out to.
The debug configurations explicitly pass --target x86_64-unknown-linux-gnu
(or the equivalent native target). Make sure that target is installed:
# Linux
rustup target add x86_64-unknown-linux-gnu
# macOS Apple Silicon
rustup target add aarch64-apple-darwin
# macOS Intel
rustup target add x86_64-apple-darwinIf you are on a non-Linux host, update the "args" in .vscode/launch.json
to match your native triple.
Make sure the server was started with --inspect (or --inspect-brk to pause
before the first line). The default npm run dev script does not pass --inspect;
start it manually or add a separate dev:debug npm script:
"dev:debug": "node --inspect ./node_modules/.bin/tsx src/index.ts"Then run "Start API Server" normally and attach.
Disable the contracts/bbs_plus_v1 crate from the workspace if you are not
actively working on it — it's excluded from the Cargo workspace by default
(exclude in root Cargo.toml) but may still be indexed if you open files
from it. Close those tabs to stop rust-analyzer from analysing it.
Copy the example file and fill in your values:
cp .env.example .envThe "Validate Environment" task will report which variables are missing.
Domain-specific words (soroban, groth, plonk, wasm, etc.) are already in
the workspace cSpell.words list. To add more, open .vscode/settings.json and
append to that array.