@titon-network/automaton
v0.2.0
Published
Production-ready off-chain automaton node for the Titon protocol suite (Kronos automation, Fortuna VRF). Stake once with ForgeTON, earn across every admitted consumer product.
Maintainers
Readme
@titon-network/automaton
AI assistants / LLM-driven development — start here: read
AGENTS.md(compact quick reference) orCLAUDE.md(full architecture + navigator tables). Task recipes live in.claude/commands/. Every DX surface is catalogued on one page atdocs/dx.md. Single-command gate:pnpm run verify. Machine-readable CLI:automaton doctor --format json·automaton status --format json.
The off-chain operator node for the Titon protocol suite on TON.
Stake once with ForgeTON (shared-security staking pool) and earn from every admitted consumer product — today Kronos automation; tomorrow Fortuna VRF, oracles, functions.
automaton init # first-run setup: wallet, network, config
automaton stake register 10 # register on-chain with 10 TON stake
automaton run # start the daemonThat's the happy path. The rest of this README covers installation, configuration, and operations.
Install
Three ways to get the automaton binary. Pick one.
npm (Node.js ≥ 22)
npm install -g @titon-network/automaton
automaton --versionNote: v0.1.0 ships the build pipeline but the sibling SDKs it depends on (
@titon-network/kronos-sdk,@titon-network/forgeton-sdk) are not yet published to npm. Install-from-source or Docker is the operational path until they land. See Current status.
Docker
docker pull titon/automaton:latest
docker run --rm titon/automaton:latest --versionA full daemon run (assuming you've run automaton init on the host and mounted the resulting directory):
docker run -d \
--name automaton \
--restart unless-stopped \
-v ~/.titon:/home/nonroot/.titon:rw \
-e AUTOMATON_PASSWORD=...your-keystore-password... \
-p 127.0.0.1:9090:9090 \
titon/automaton:latest runThe image is built from distroless/nodejs22, runs as UID 65532 (nonroot), and ships multi-arch (amd64 + arm64). Full details in docs/ops.md.
From source
git clone https://github.com/titon/titon.git
cd titon/automaton
pnpm install
pnpm run build
./dist/cli/index.js --versionThe repo is a four-directory workspace (see titon repo layout); pnpm resolves sibling SDK dependencies via file: links.
Quickstart
Goal: first execution reward on testnet, in under 5 minutes.
See docs/quickstart.md for the full walk-through. The short version:
# 1. Scaffold ~/.titon/automaton/ (wallet + config)
automaton init --network testnet
# 2. Fund the wallet printed at the end of init — you need ≥ 11 TON
# (10 stake minimum + 1 for gas). Testnet faucet:
# https://t.me/testgiver_ton_bot
automaton doctor # verify the install
# 3. Register as an automaton on-chain
automaton stake register 10
# 4. Start the daemon — executes due jobs, tails slash events
automaton runThe daemon prints one JSON line per event to stdout and exposes Prometheus metrics + health probes at http://127.0.0.1:9090/metrics · /healthz · /readyz.
Subcommands
| Command | What it does |
|---|---|
| automaton init | First-run setup. Creates ~/.titon/automaton/{config.json, wallet.enc}. Interactive by default; pass --network, --import-mnemonic <file>, --password-file <file> for fully non-interactive CI runs. |
| automaton doctor | Install + runtime preflight — Node version, SDK resolvability, config/keystore presence, RPC reachability, balance vs minFreeBalance, schema-version match, lockfile status. Exits non-zero on any failure; skips chain-dependent checks when no deployment is live (mainnet today). --format json for agent-parseable output. |
| automaton status | Read-only operator snapshot — network, wallet balance, automaton registration (stake / slashCount / registered-at), pool active-count, drift counters, endpoint ring, lockfile. Best-effort chain reads; transient errors land in a footer. --format json emits a stable machine-readable payload (bigints encoded as {nano, ton} pairs; endpoint apiKeys stripped). |
| automaton stake register <amount> | First-time registration with <amount> TON collateral. Pool minimum is 10 TON; operator-wallet must additionally hold ~0.07 TON for gas + consumer-fan-out. |
| automaton stake increase <amount> | Top up the staked collateral. Refuses if not registered, inactive, or unstake pending. |
| automaton stake request-unstake | Start the cooldown (default 24 h on ForgeTON). Stake stays locked until withdraw. |
| automaton stake cancel-unstake | Abort a pending unstake and stay active. |
| automaton stake withdraw | Finalize after the cooldown — returns the full stake to the wallet. |
| automaton run | Start the daemon. Foreground; use systemd or Docker to daemonize. Signals: SIGTERM/SIGINT = graceful shutdown (drains in-flight txs, flushes state); SIGHUP = warn-and-ignore (restart to reload config). --log-level overrides config.logLevel. |
| automaton config show | Inspect the effective config (file + env overlay), with env overrides surfaced as a delta block. --format json dumps a stable payload (apiKeys redacted). Read-only. |
| automaton config edit | Open the config in $EDITOR (or --editor=<cmd>), then re-run the zod validator on save. Offers to re-open on validation failure. |
| automaton config validate [path] | Dry-run validate a config file against the zod schema. Useful before restarting the daemon with a hand-edited config. --format json available. |
| automaton completion <shell> | Print a bash / zsh / fish completion script. Install with eval "$(automaton completion bash)" or dump to your shell's fpath. |
Every subcommand accepts --help.
Configuration
Config lives at ~/.titon/automaton/config.json (or $AUTOMATON_CONFIG, or under $TITON_HOME/automaton/). Generated by automaton init; hand-editable afterwards.
| Field | Type | Default | Purpose |
|---|---|---|---|
| configVersion | 1 | — | Schema-version; loaders reject mismatch. Bump on any field change. |
| network | 'testnet' | 'mainnet' | — | Which chain to run against. Wallets are network-aware (different address per network for the same mnemonic); set this correctly at init time. |
| endpoints | array of {url, apiKey?} | toncenter | Failover ring. Daemon rotates on transient errors (timeouts, 429, 5xx). Public toncenter is rate-limited without an API key (~1 req/s) — fine for testnet, swap in a paid endpoint for mainnet. |
| walletVersion | 'v5r1' | 'v5r1' | TON wallet contract version. Only V5R1 is supported today. |
| metricsPort | number | 9090 | Bind port for /metrics · /healthz · /readyz. |
| metricsHost | string | '127.0.0.1' | Bind host. Keep local for systemd installs; flip to '0.0.0.0' for Docker publishes. |
| pollIntervalMs | number | 10_000 | Main-loop poll interval. Also the staleness threshold for /healthz (= 2× this value, floor 10 s). |
| gaugeSnapshotEveryNTicks | number | 6 | Refresh Prometheus gauges (balance / stake / drift) every Nth tick. Default ~60 s at the default tick. Lower for faster dashboards; higher to reduce RPC quota. |
| alertWebhookUrl | url | (unset) | Webhook POSTed on self-slash (fire-and-forget, 5 s timeout). JSON body includes txHash; consumers should dedupe on it. |
| maxGasPerExecute | TON | '0.5' | Per-execute gas ceiling. |
| minFreeBalance | TON | '2.0' | automaton doctor warns below this. |
| logLevel | trace | debug | info | warn | error | info | Pino log level. --log-level flag overrides. |
| products.kronos / products.fortuna | bool | true / false | Enable per-consumer workers. Fortuna ships in a future phase. |
Env-var overrides for the common toggles: AUTOMATON_NETWORK, AUTOMATON_METRICS_PORT, AUTOMATON_LOG_LEVEL, AUTOMATON_PASSWORD, TITON_HOME, AUTOMATON_CONFIG.
Operations
Metrics. The daemon exposes Prometheus metrics at http://<metricsHost>:<metricsPort>/metrics. Every counter/gauge/histogram is declared in one place (src/daemon/metrics.ts) with a help string; the names follow automaton_<subsystem>_<metric>[_unit]. See docs/ops.md for Grafana pointers.
Health probes.
/healthz→ 200 iff the last poll cycle completed within2 × pollIntervalMs(floor 10 s). Use as a Kubernetes liveness probe or systemd watchdog./readyz→ 200 iff lockfile held + wallet unlocked + stake active + RPC reachable. Body lists per-check detail. Use as a Kubernetes readiness probe.
Logs. JSON lines on stdout via pino. warn + error go to stderr. Redacted fields: password, mnemonic, privateKey, seed, secretKey (top-level + one level deep). Stream via journalctl -u automaton -f under systemd, or docker logs -f under Docker.
Shutdown. SIGTERM or SIGINT triggers graceful shutdown: stop accepting new work, wait up to 30 s for in-flight Execute txs to confirm, flush event checkpoint, release lockfile, exit 0. A second signal hard-exits with code 130 (for operators hammering Ctrl-C). systemd units should give ≥ 45 s TimeoutStopSec.
Exit codes. 0 = clean shutdown. 1 = crash. 75 = lockfile held by another instance (EXIT_LOCK_HELD; systemd uses RestartPreventExitStatus=75 to avoid respawn loops). 130 = force-exit on double signal.
Full operational reference: docs/ops.md. Troubleshooting: docs/troubleshooting.md.
Architecture
The daemon is a composition of small, independently testable pieces:
automaton run
├── lockfile (single-instance)
├── keystore unlock (scrypt + AES-256-GCM)
├── chain runtime (FailoverTonClient + opened Kronos registry + ForgeTON pool)
├── schema check (refuses to start on SDK/contract version drift)
├── event drain (tails registry + pool tx history; dispatches to handlers)
├── worker loop (decide → submit Execute → verify via executionCount delta)
├── metrics + pino (prom-client /metrics + redacted JSON logs)
└── health server (/healthz + /readyz + /metrics on config.metricsHost:metricsPort)Design decisions are documented at the top of each module. CLAUDE.md is the navigator — start there if you want to contribute.
Current status
- Kronos: testnet live. Production-grade deploy, ~126 contract tests + cross-contract integration coverage.
- ForgeTON: testnet live.
- @titon-network/automaton: v0.1.0 feature-complete for Kronos. Full jest suite gated through
pnpm run verify. npm publish gated on SDK publication; Docker + from-source path works today. - Fortuna: not yet built. Deferred to a later phase.
See ../kronos/progress.md for the full roadmap.
License
MIT.
Contributing
Issues + PRs welcome at github.com/titon/titon. New to the codebase? CLAUDE.md has the AI + human navigator tables; AGENTS.md is the compact version for scripted tools.
