ChainSafe / ChainSafe/canton-middleware

Refactor: Project structure

Open
#121 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
1
Forks
1
Avg merge
40m
Merged PRs (30d)
1

Description

# Canton Middleware Refactor Plan (Step-by-step, Domain-driven)

## Goals

* **Minimal `cmd`**: `cmd/api` and `cmd/relayer` should only load config + call `app.Run`.
* **Feature/domain-first structure** (Go idiomatic): code organized by capability (token, registration, relayer, ethapi), not by “layers” folders.
* **Clear dependency direction**:

* HTTP handlers depend on services
* services depend on store/repositories
* domain logic does **not** depend on HTTP/DB/framework packages
* HTTP handlers are clean and minimal.
* **Fix DB ownership & coupling**: Each db/store should be inside the domain level.(registration/store/).

---

## 1) Current structural issues
- Package responsibilities are mixed
- Cross-component coupling via “optional” dependencies
- DB access is unstructured / inconsistent
- Lack of domain modeling / invariants
- Transport concerns leak into core logic

---

## 2) Domain-driven approach (Go-practical)

### 2.1 Define bounded contexts (modules)

Treat these as separate “domains” with clear boundaries:

1. **Registration Domain**

* User registration related business logic.

3. **Token Domain**

* ERC20-related business behaviors exposed via API.
4. **Relayer Domain**

* Background processing of bridge work (poll/stream, submit tx, update transfer status).
5. **Eth API Domain**

* Exposed endpoints for EVM-facing operations.

Each module owns:

* its **service** (application logic)
* its **repo interface**
* its **repo implementation** (postgres)
* its **http handler** (only for API-exposed modules)

### 2.2 Architecture pattern (Ports & Adapters)

Keep it simple:

* **Domain / Service**: pure logic + interfaces
* **Repository adapters**: Postgres implementations
* **Transport**: Echo handlers

Dependency direction:

`echo handler -> service -> repo interface -> repo postgres -> db`

Canton/Ethereum clients are adapters injected into services.

### 2.3 Resulting repo structure

```
cmd/
api/
main.go
relayer/
main.go

config/
config.go

pkg/
app/
api/
server.go
relayer/
server.go
app.go // shared logic and interface defination
errors.go // defines http errors and conversion

migrations
1_create_table_user.go. // Database migrations file
...
migrations.go

registration/
service/
http.go // http handler
rpc.go. // if needed
grpc.go // if needed
service.go // actual business logic
store/
store.go // defines the interface for the store
pg/ //postgress implementation
model.go // defines the DAO for tables
pg.go // postgress implementation of the store
mock/ //mock implementation

token/
service/
store/

....

```

---

## 3) cmd → app

### 3.1 `cmd/api/main.go` (minimal)

```go
package main

import (
"context"
"log"
"os"
"os/signal"
"syscall"

"yourrepo/config"
"yourrepo/pkg/app/api"
)

func main() {
cfg, err := config.Load()
if err != nil { log.Fatalf("config: %v", err) }

ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()

app, err := api.New(cfg)
if err != nil { log.Fatalf("api init: %v", err) }

if err := app.Run(ctx); err != nil {
log.Fatalf("api run: %v", err)
}
}
```

### 3.2 `cmd/relayer/main.go` (minimal)

```go
package main

import (
"context"
"log"
"os"
"os/signal"
"syscall"

"yourrepo/config"
"yourrepo/pkg/app/relayer"
)

func main() {
cfg, err := config.Load()
if err != nil { log.Fatalf("config: %v", err) }

ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()

app, err := relayer.New(cfg)
if err != nil { log.Fatalf("relayer init: %v", err) }

if err := app.Run(ctx); err != nil {
log.Fatalf("relayer run: %v", err)
}
}
```

---

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by comparing cmd/api/main.go and cmd/relayer/main.go with the proposed minimal entry points, then read config/config.go and the pkg/app/api, pkg/app/relayer, and domain package structure. Done means command entry points only load configuration and run the app, with registration, token, relayer, and Eth API responsibilities separated behind the stated service, repository, and transport boundaries.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
backend
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.