Skip to content

[E2E] Devstack: Layer 2 (service shims) #180

@sadiq1971

Description

@sadiq1971

Context

Layer 2 provides concrete implementations of each stack interface. Each shim wraps a real service client (go-ethereum, HTTP, database/sql) and satisfies the interface defined in Layer 1. No mocks — shims talk to real services running in Docker.

Files to Create

All files in tests/e2e/devstack/shim/, all with //go:build e2e.

anvil.go

Implements stack.Anvil. Uses go-ethereum/ethclient.

  • Constructor: NewAnvil(manifest *stack.ServiceManifest) (stack.Anvil, error)
  • Dials manifest.AnvilRPC via ethclient.Dial.
  • Loads ABIs from embedded Foundry artifact JSON using //go:embed:
    • contracts/ethereum-wayfinder/out/PromptToken.sol/PromptToken.json
    • contracts/ethereum-wayfinder/out/CantonBridge.sol/CantonBridge.json
  • ERC20Balance: packs balanceOf(owner) calldata, calls client.CallContract, unpacks result.
  • ApproveAndDeposit:
    1. Signs and sends approve(bridgeAddr, amount) on the token contract.
    2. Signs and sends deposit(amount, partyID) on the bridge contract.
    3. Returns the deposit tx hash.

canton.go

Implements stack.Canton. Simple health-check wrapper.

  • Constructor: NewCanton(manifest *stack.ServiceManifest) stack.Canton
  • IsHealthy: HTTP GET manifest.CantonHTTP + "/v2/version" — returns true on 200.

apiserver.go

Implements stack.APIServer. HTTP client.

  • Constructor: NewAPIServer(manifest *stack.ServiceManifest) stack.APIServer
  • Register: POST /register with {evm_address, signature, message} JSON body.
  • GetBalance: JSON-RPC eth_call to /eth — calls balanceOf(owner) on the token contract.
  • Transfer: JSON-RPC eth_sendTransaction to /eth.
  • Health: GET /health — returns nil on 200.

relayer.go

Implements stack.Relayer. HTTP client.

  • Constructor: NewRelayer(manifest *stack.ServiceManifest) stack.Relayer
  • Health: GET /health.
  • IsReady: GET /ready — returns true on 200.

indexer.go

Implements stack.Indexer. HTTP client with a generic helper.

  • Constructor: NewIndexer(manifest *stack.ServiceManifest) stack.Indexer
  • All methods use a shared getJSON[T](client, url) generic helper that GETs, checks status, and decodes.
  • Endpoints follow the pattern /indexer/v1/admin/... (see docs/E2E_TEST_ARCHITECTURE.md §5 for full URL list).

postgres.go

Implements stack.Postgres. Uses database/sql with lib/pq driver.

  • Constructor: NewPostgres(manifest *stack.ServiceManifest) (stack.Postgres, error)
  • WhitelistAddress: INSERT INTO whitelist (evm_address) VALUES ($1) ON CONFLICT DO NOTHING
  • GetUserByEVMAddress: SELECT evm_address, canton_party_id, fingerprint FROM users WHERE evm_address = $1; returns nil, nil for no-rows.

Acceptance Criteria

  • go build ./tests/e2e/devstack/shim/... compiles cleanly with -tags e2e.
  • Each shim struct satisfies its corresponding stack interface (compiler-enforced via var _ stack.Anvil = (*anvilShim)(nil) assertions).

Dependencies

Notes

  • Do not use testcontainers-go here. Shims connect to services already running in Docker.
  • The go:embed path for ABI files must be relative to the package; use a symlink or path alias if needed.
  • ApproveAndDeposit should use bind.NewKeyedTransactor pattern consistent with the rest of the codebase.

Size

M (1–2 days)

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