ChainSafe / ChainSafe/canton-middleware
Refactor: Project structure
- 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