Skip to content

RFC: Declarative test-fixture specification (calyx.yaml) for multi-contract CI provisioning #586

Description

@MuhamadHamzah

Summary

I'd like to propose a discussion around a declarative fixture specification for provisioning multi-contract Soroban test states (accounts, SAC/classic trustlines, WASM deployments, and cross-contract initialization) as a companion extension to stellar-scaffold/cli, rather than a competing tool.

Problem & Community Context

Integration testing multi-contract Soroban projects (e.g., an AMM pool that depends on a freshly deployed token address) currently requires either:

  • Hand-written bash chains of stellar-cli calls, which are flaky in CI (nonce races, Friendbot rate limits, ~30-90s per run), or
  • Manually specifying every --address flag to stellar snapshot create after the fact, which is a post-hoc dump and can't express dynamic dependencies between entities that don't exist yet at snapshot time.

While tools like Chef focus on rapid local test environment and sandbox setup, there remains an unaddressed gap in declarative fixture orchestration: defining interdependent contract states declaratively and compiling that state into reusable ledger snapshots.

This directly connects to the gap identified in #170 regarding multi-contract test setup (e.g., creating test accounts and deploying interdependent token contracts as a "before all" block rather than maintaining fragile initialize.sh scripts, as well as exploring ledger snapshot testing).

While #181 explored broader configuration restructuring (environments.toml vs scaffold.yml), this proposal intentionally sidesteps that unresolved debate. Instead, it targets Scaffold's already-shipped extension architecture (#414), providing an immediately usable solution today regardless of future config file evolutions.

Proposal

I'm building Calyx, an open-source (Apache-2.0/MIT) engine that:

  1. Accepts a declarative calyx.yaml manifest specifying accounts, assets, WASM deployments, and initialization calls (with dynamic ${contracts.x.address} cross-references resolved via topological sort).
  2. Provisions that state against a running node (e.g., stellar/quickstart), handling sequence nonce coordination and Friendbot retry backoff.
  3. Exports the provisioned state directly into Stellar's official ledger snapshot JSON format, consumable natively by soroban-sdk::Env::from_ledger_snapshot_file().
  4. Computes a deterministic SHA-256 State Integrity Hash over the provisioned entries so CI runners can assert environment readiness (calyx verify) before test suites execute.

Where Chef helps developers quickly bootstrap test environments, Calyx operates at the application fixture layer: compiling declarative contract dependencies into reproducible snapshots and type-safe test constants.

Rather than shipping this as an isolated standalone CLI, I'd like it to integrate with stellar-scaffold/cli using the existing extension mechanism shipped in #414 (a PATH-resolved binary stellar-scaffold-plugin-calyx registered via config.extensions / environments.toml, following the pattern of the built-in reporter extension), hooking into the post-deploy stage to provision test fixtures automatically right after contracts are deployed.

What I'm asking

  • Is this a direction the maintainers would be open to, either as a community extension referenced in the docs, or eventually folded closer into the toolchain?
  • Are there existing conventions for extension hook points (pre/post-deploy, pre/post-build) I should target so this composes cleanly with other extensions?
  • Any prior art or architectural constraints around declarative fixture/snapshot provisioning I should be aware of before finalizing the schema?

Happy to open a draft PR with a working extension once the schema is finalized, if that's useful for evaluation. Feedback is very welcome; even "this doesn't fit the project's direction" is useful signal.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions