Skip to content

[E2E] Devstack: Layers 4/5/6 (System + DSL + Presets) #181

@sadiq1971

Description

@sadiq1971

Context

This issue wires the entire devstack together: System (Layer 4) holds all shims and provides the composed view of the running stack; DSL (Layer 5) provides high-level test operations; Presets (Layer 6) provide one-line test entry points (NewFullStack(t)).

After this issue, writing a new E2E test requires only:

sys := presets.NewFullStack(t)
sys.DSL.RegisterUser(t, sys.Accounts.User1)

Files to Create

All with //go:build e2e.

tests/e2e/devstack/system/system.go

package system

type System struct {
    Anvil     stack.Anvil
    Canton    stack.Canton
    APIServer stack.APIServer
    Relayer   stack.Relayer
    Indexer   stack.Indexer
    Postgres  stack.Postgres
    DSL       *dsl.DSL
    Manifest  *stack.ServiceManifest
    Accounts  *Accounts
}

type Accounts struct {
    User1 *stack.Account  // AnvilAccount0
    User2 *stack.Account  // AnvilAccount1
}

// New wires all shims from the manifest and returns a ready System.
func New(t *testing.T, manifest *stack.ServiceManifest) *System

tests/e2e/devstack/dsl/dsl.go

High-level operations:

Method Description
RegisterUser(t, acc) Whitelist + EIP-191 sign + POST /register
Deposit(t, acc, amount) Anvil.ApproveAndDeposit
Withdraw(t, acc, amount, toEVMAddr) APIServer.Transfer to relayer withdrawal addr
Transfer(t, from, to, amount, token) APIServer.Transfer between two Canton parties
GetBalance(t, acc, token) APIServer.GetBalance
MintDEMO(t, acc, amount) Direct Canton DAML command via APIServer
WaitForCantonBalance(t, acc, token, expected) Poll with 30s timeout
WaitForRelayerReady(t) Poll Relayer.IsReady with 60s timeout
GetIndexerBalance(t, partyID, admin, id) Indexer.GetBalance
WaitForIndexerBalance(t, partyID, admin, id, expected) Poll with 60s timeout
GetIndexerTotalSupply(t, admin, id) Indexer.TotalSupply
WaitForIndexerTotalSupply(t, admin, id, expected) Poll with 60s timeout
GetIndexerEvent(t, contractID) Indexer.GetEvent
WaitForIndexerEvent(t, partyID, eventType) Poll Indexer.ListPartyEvents until event appears, 60s timeout
ListIndexerPartyEvents(t, partyID, eventType) Indexer.ListPartyEvents

Polling pattern — all WaitFor* helpers use require.Eventually with the appropriate timeout (30s for Canton, 60s for Indexer) and a 500ms interval.

tests/e2e/devstack/dsl/helpers.go

func signEIP191(message, privateKey string) (string, error)
func balanceEquals(a, b string) bool       // decimal string comparison
func addDecimal(a, b string) string
func subtractDecimal(a, b string) string
func toWei(decimal string) *big.Int
func fromWei(wei *big.Int) string

tests/e2e/devstack/presets/presets.go

// DoMain starts the compose stack and runs m.Run(). Called from TestMain.
func DoMain(m *testing.M, opts ...Option) int

// NewFullStack starts the full stack (anvil + canton + postgres + api-server + relayer + indexer).
// Registers t.Cleanup to stop the stack.
func NewFullStack(t *testing.T, opts ...Option) *system.System

// NewAPIStack starts only api-server + dependencies (no relayer, no indexer).
func NewAPIStack(t *testing.T, opts ...Option) *system.System

// NewIndexerStack starts api-server + relayer + indexer.
func NewIndexerStack(t *testing.T, opts ...Option) *system.System

tests/e2e/devstack/presets/options.go

type Option func(*config)

func WithComposeFile(path string) Option
func WithProjectName(name string) Option

func envOr(key, fallback string) string

Default compose file: tests/e2e/docker-compose.e2e.yaml (resolved relative to repo root via runtime.Caller).
Default project name: canton-e2e.

Acceptance Criteria

  • go build ./tests/e2e/devstack/... compiles cleanly with -tags e2e.
  • presets.DoMain + presets.NewFullStack work against a running stack (manual smoke test).
  • WaitForIndexerBalance uses 60s timeout; WaitForCantonBalance uses 30s timeout.

Dependencies

Size

M (1 day)

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