gcx/backend/services/translate-service/internal/domain/entity/address_mapping.go

97 lines
2.7 KiB
Go

package entity
import (
"fmt"
"time"
"github.com/genex/translate-service/internal/domain/vo"
)
// AddressMapping is the aggregate root that maps an internal platform address
// to an on-chain address for a given blockchain network.
type AddressMapping struct {
ID string `json:"id"`
UserID string `json:"userId"`
InternalAddress string `json:"internalAddress"`
ChainAddress string `json:"chainAddress"`
ChainType string `json:"chainType"`
IsActive bool `json:"isActive"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
// NewAddressMapping is the factory method that creates a fully validated AddressMapping.
// It enforces all domain invariants at creation time.
func NewAddressMapping(id, userID, internalAddr, chainAddr, chainType string) (*AddressMapping, error) {
if id == "" {
return nil, fmt.Errorf("mapping ID must not be empty")
}
if userID == "" {
return nil, fmt.Errorf("user ID must not be empty")
}
// Validate internal address via value object
if _, err := vo.NewAddress(internalAddr); err != nil {
return nil, fmt.Errorf("invalid internal address: %w", err)
}
// Validate chain address via value object
if _, err := vo.NewAddress(chainAddr); err != nil {
return nil, fmt.Errorf("invalid chain address: %w", err)
}
// Validate chain type via value object
if _, err := vo.NewChainType(chainType); err != nil {
return nil, err
}
now := time.Now()
return &AddressMapping{
ID: id,
UserID: userID,
InternalAddress: internalAddr,
ChainAddress: chainAddr,
ChainType: chainType,
IsActive: true,
CreatedAt: now,
UpdatedAt: now,
}, nil
}
// Validate checks all domain invariants on an existing mapping.
func (m *AddressMapping) Validate() error {
if m.ID == "" {
return fmt.Errorf("mapping ID must not be empty")
}
if m.UserID == "" {
return fmt.Errorf("user ID must not be empty")
}
if _, err := vo.NewAddress(m.InternalAddress); err != nil {
return fmt.Errorf("invalid internal address: %w", err)
}
if _, err := vo.NewAddress(m.ChainAddress); err != nil {
return fmt.Errorf("invalid chain address: %w", err)
}
if _, err := vo.NewChainType(m.ChainType); err != nil {
return err
}
return nil
}
// Deactivate marks the mapping as inactive.
func (m *AddressMapping) Deactivate() {
m.IsActive = false
m.UpdatedAt = time.Now()
}
// Activate marks the mapping as active.
func (m *AddressMapping) Activate() {
m.IsActive = true
m.UpdatedAt = time.Now()
}
// BelongsToUser checks whether this mapping belongs to the specified user.
func (m *AddressMapping) BelongsToUser(userID string) bool {
return m.UserID == userID
}