GreenFloor is a Chia CAT market-making system with native Rust operator binaries
backed by the canonical greenfloor-engine crate.
greenfloor-managerandgreenfloordare Cargo binaries (no Python entrypoints).- Rust owns vault signing, offer construction, coin-op execution, daemon cycles, config validation for operator commands, and SQLite persistence.
- Python remains for
scripts/only (bootstrap + subprocess adapters). See AGENTS.md → Python (scripts and test harnesses only) for scope rules. - No PyO3 extension.
greenfloor-manager: native manager CLI for config validation, key onboarding, coin inventory/reshaping, offer building/posting, and operational checks. Script adapters:program-fields,markets-fields,cats-fields,materialize-minimal-program.greenfloord: native daemon process that evaluates configured markets, executes offers, and runs the market cycle.greenfloor-engine/: Rust crate for canonical signing, offer, coin-op, and cycle policy.
- Scope and architecture:
docs/plan.md - Operator deployment/recovery:
docs/runbook.md - Architecture decisions index:
docs/README.md(start with ADR 0015 for on-chain cancel)
- Offer files are plaintext Bech32m payloads with prefix
offer1.... - In
chia-wallet-sdk, offer text is an encoded/compressedSpendBundle(encode_offer/decode_offer). - Manager offer publishing validates offer text in Rust before Dexie submission.
- Venue submission sends that exact offer text string as the
offerfield to the venue API.
- Every posted offer should have an expiry.
- Stable-vs-unstable pairs should use shorter expiries than other pair types.
- Explicit cancel operations are rare and policy-gated.
- Cancel is only for stable-vs-unstable pairs and only when unstable-leg price movement is strong enough to justify early withdrawal.
- Cancellation is on-chain: Dexie supplies the offer file only; GreenFloor spends the offered input coin back to vault change via Coinset and records
cancel_submitteduntil reconcile confirmscancelled(see ADR 0015). - Default behavior remains expiry-driven rotation instead of frequent cancel/repost churn.
Build and install native operator binaries:
cargo install --path greenfloor-engine --binsBootstrap home directory first (required for real deployment):
greenfloor-manager bootstrap-homeValidate config and check readiness:
greenfloor-manager config-validate
greenfloor-manager doctor
# Script-friendly compact JSON (default output is pretty JSON):
greenfloor-manager --json doctorOnboard signing keys:
greenfloor-manager keys-onboard --key-id <your-key-id>Build and post offers:
# Dry-run preflight
greenfloor-manager build-and-post-offer --pair ECO.181.2022:xch --size-base-units 1 --dry-run
# Publish (mainnet default)
greenfloor-manager build-and-post-offer --pair ECO.181.2022:xch --size-base-units 1
# Publish on testnet11
greenfloor-manager build-and-post-offer --pair TDBX:txch --size-base-units 1 --network testnet11Vault KMS / signer operations:
# List vault inventory (XCH + CAT)
greenfloor-manager coins-list
# Split one coin into target denominations (waits through signature + mempool + confirmation + reorg watch)
greenfloor-manager coin-split --pair TDBX:txch --coin-id <coin-id> --amount-per-coin 1000 --number-of-coins 10
# Combine small coins into one larger coin (waits through signature + mempool + confirmation + reorg watch)
greenfloor-manager coin-combine --pair TDBX:txch --input-coin-count 10 --asset-id xchCoin-op wait diagnostics include:
signature_wait_warningandsignature_wait_escalation(soft-timeout style, manager keeps waiting).in_mempoolwith acoinset_urlon every mempool user event.confirmedplus read-only Coinset reconciliation metadata.reorg_watch_*events while waiting for six additional blocks after first confirmation.
On testnet11, use txch as the quote symbol in pair arguments (for example TDBX:txch).
Check offer status and reconcile:
greenfloor-manager offers-status
greenfloor-manager offers-reconcileoffers-reconcile now emits canonical taker-detection signals from offer-state transitions (taker_signal) and keeps mempool/chain status pattern checks as advisory diagnostics (taker_diagnostic).
Run the daemon:
greenfloord --program-config config/program.yaml --markets-config config/markets.yaml --oncePost-Python-cutover local development uses three runtimes. None of them replace the others — each owns a distinct slice of the repo.
| Runtime | Role | Install |
|---|---|---|
Rust (stable + cargo) |
Operator binaries (greenfloor-engine, greenfloor-manager, greenfloord), fmt/clippy, and the primary test suite |
rustup; optional cargo install cargo-nextest for faster tests |
Python 3.11+ (.venv) |
Script adapters under scripts/, ruff/pyright/yamllint pre-commit hooks |
python3 -m venv .venv && source .venv/bin/activate && pip install -e ".[dev]" |
| Node.js LTS | Prettier pre-commit hook (YAML/JSON/Markdown) | fnm, nvm, or brew install node@24; CI uses node-version: lts/* |
Operators are Rust-only. Do not pip install expecting greenfloor-manager or
greenfloord console scripts — build with cargo install --path greenfloor-engine --bins
or cargo build --manifest-path greenfloor-engine/Cargo.toml --bins.
Python is not gone. It remains for script subprocess bridges and dev lint/type-check only. See AGENTS.md → Python (scripts and test harnesses only).
Node is easy to miss. Pre-commit's Prettier hook needs node on your PATH. If
pre-commit run --all-files fails on the prettier hook with “node not found”, install
Node LTS and verify node --version before retrying.
One-time setup (install order: Rust and Node LTS from Local dev tooling above, then Python venv):
# Rust (operators + tests): cargo install --path greenfloor-engine --bins
# Node LTS: verify `node --version` before pre-commit
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -e ".[dev]"Run local checks:
export PRE_COMMIT_HOME="$(pwd)/.cache/pre-commit" # reuse hook envs; CI caches this path
pre-commit run --all-files # ruff, pyright, prettier, yamllint, cargo fmt/clippy (~5–10s warm)Full gate before push (Rust fmt/clippy via pre-commit — clippy::all + clippy::pedantic with documented allows; clippy runs with --lib --bins --tests):
cargo nextest run --manifest-path greenfloor-engine/Cargo.toml --features test-supportcargo test with the same manifest also works when cargo-nextest is not installed.
Full gate details: docs/plan.md → Delivery constraints.
Operator overrides (all optional):
GREENFLOOR_KEY_ID_FINGERPRINT_MAP_JSON— JSON map for key ID -> fingerprint; normally injected fromprogram.yamlsigner key registry by daemon path.GREENFLOOR_CHIA_KEYS_DERIVATION_SCAN_LIMIT— integer derivation depth scan limit for matching selected coin puzzle hashes (default200).GREENFLOOR_COINSET_BASE_URL— custom Coinset API base URL for coin queries andpush_tx; when unset, scripts default to mainnet and can select testnet11 via--network.coin_ops.minimum_fee_mojos(in program config) — fallback minimum fee for coin operations when Coinset advice is unavailable (default10000000mojos /0.00001 XCH; can be set to0).
Signer program config contract (program.yaml):
signer.kms_key_id— AWS KMS key for vault member signing.signer.kms_region— AWS region for KMS calls.vault.launcher_id— vault singleton launcher id (hex).vault.custody_keys/vault.recovery_keys— member public keys for the vault puzzle.
Legacy cloud_wallet: blocks are rejected at config load; use signer: + vault: instead.
CI secret for optional live testnet workflow:
TESTNET_WALLET_MNEMONIC— importable wallet mnemonic used by.github/workflows/live-testnet-e2e.ymlforkeys-onboardmnemonic import.- Format: whitespace-delimited
12or24words (plain text mnemonic). - Testnet receive-address example for this wallet:
txch1t37dk4kxmptw9eceyjvxn55cfrh827yf5f0nnnm2t6r882nkl66qknnt9k.
Live testnet11 proof workflow (CI-only mnemonic path):
- Dispatch
.github/workflows/live-testnet-e2e.ymlfrom GitHub Actions. - Inputs:
network_profile(default:testnet11)pair(default:TDBX:txch)size_base_units(default:1)dry_run(falseto run live post/status/reconcile evidence path)
- The workflow always runs
doctor+ dry-runbuild-and-post-offer; whendry_run=falseit additionally runs livebuild-and-post-offer,offers-status, andoffers-reconcile. - Logs are uploaded as artifact
live-testnet-e2e-artifacts.
Testnet11 asset bootstrap helper workflow (G2):
- Dispatch
.github/workflows/testnet11-asset-bootstrap-helper.yml. - It discovers Dexie testnet CAT candidates and uploads
g2-testnet-asset-bootstrap-artifacts. - Use
markets-snippet.yamlfrom the artifact as a starter config snippet forsupported_assets_exampleandmarketsstanzas.
Signer key resolution contract is repo-managed through program.yaml:
keys.registry[].key_idmust match marketsigner_key_idkeys.registry[].fingerprintis required for deterministic signer mapping- optional
keys.registry[].networkis validated againstapp.network
V1 intentionally sends only one push notification type:
- low-inventory alerts for sell-side CAT/XCH assets.
Alert content includes ticker, remaining amount, and receive address.