Skip to main content
This walks through everything from a clean clone to a finished ward test report. It takes about 10–15 minutes of hands-on time, plus one manual step you can’t skip: funding two TestNet accounts through Algorand’s captcha-gated dispensers.
Ward targets Algorand TestNet by default — no LocalNet or AlgoKit CLI install required. See why in the decision log.

1. Prerequisites

Node.js 20+

Ward’s engines.node field requires Node 20 or newer.

Docker

Needed to self-host the facilitator via docker-compose.yml.

2. Clone and configure

.env.example documents every variable Ward’s CLI, self-hosted facilitator, and paid verification server need — see the full breakdown in Environment Variables.

3. Generate accounts

This script:
  1. Generates a fresh Algorand keypair for each account Ward needs (WARD_FUNDER, WARD_CLIENT, WARD_PAYTO, AVM_PRIVATE_KEY) and prints the address + base64 secret key for each.
  2. Generates throwaway, well-formed EVM and SVM keys purely to satisfy the upstream facilitator example’s multi-chain startup check — they’re never funded or used to sign anything real.
Paste every printed value into .env.

4. Fund the two bootstrap accounts

Algorand’s TestNet dispensers are captcha-gated web forms, so this one step can’t be automated. Visit each dispenser and fund:
1

Fund WARD_FUNDER

Send TestNet ALGO to the WARD_FUNDER address via the ALGO dispenser. Once funded, WARD_FUNDER auto-funds every other account Ward needs — you only do this once per environment.
2

Fund AVM_PRIVATE_KEY's address

Send TestNet ALGO to the facilitator’s own signing address (the address for AVM_PRIVATE_KEY) via the same dispenser. This account co-signs settlement fee-payer transactions, so it needs its own balance.

5. Install dependencies

6. Boot the facilitator and verify one real payment

ward init is idempotent and:
  • Boots the self-hosted facilitator via docker-compose up and waits for its health check.
  • Auto-funds WARD_CLIENT and any disposable accounts from WARD_FUNDER.
  • Opts WARD_PAYTO into the test ASA (TestNet USDC) if a private key is available for it.
  • Runs one real, complete payment through /verify and /settle and confirms it on-chain, so nothing downstream runs against an unverified facilitator.

7. Run the full invariant suite

This runs all eight invariants (U1U5, A1A3), prints a pass/fail table, and writes:
  • reports/ward-report-<timestamp>.json — the full run, with reproducible evidence per invariant.
  • reports/latest.json — always the most recent run, read by ward report.
The process exits non-zero if any must-have invariant (U1, U2, U3, U4, A1) fails — safe to wire straight into CI.

8. Inspect one invariant closely

ward fuzz <id> runs a single invariant in isolation with full, verbose evidence — the fastest way to see exactly what payload Ward sent and what the facilitator returned. A1, atomic group integrity, is Ward’s headline invariant — see A1 for what it proves.

Once it’s built

The compiled dist/cli/index.js is the same binary published as ward in package.json’s bin field — use whichever entry point fits your workflow.

Next: understand what each invariant proves

Read the Invariants section before interpreting a report — a PASS or FAIL only means something once you know exactly what was tested.