package service import ( "context" "fmt" "sync/atomic" "github.com/genex/translate-service/internal/domain/entity" "github.com/genex/translate-service/internal/domain/repository" ) // TranslateService is the application service that orchestrates address mapping // operations. It depends on the domain repository interface, not a concrete // implementation — following the Dependency Inversion Principle. type TranslateService struct { repo repository.AddressMappingRepository idCounter atomic.Int64 } // NewTranslateService creates a new TranslateService with the injected repository. func NewTranslateService(repo repository.AddressMappingRepository) *TranslateService { return &TranslateService{ repo: repo, } } // CreateMapping validates inputs via the domain entity factory, persists the // mapping through the repository, and returns the created entity. func (s *TranslateService) CreateMapping(ctx context.Context, userID, internalAddr, chainAddr, chainType string) (*entity.AddressMapping, error) { id := fmt.Sprintf("map-%d", s.idCounter.Add(1)) mapping, err := entity.NewAddressMapping(id, userID, internalAddr, chainAddr, chainType) if err != nil { return nil, fmt.Errorf("domain validation failed: %w", err) } if err := s.repo.Save(ctx, mapping); err != nil { return nil, fmt.Errorf("failed to save mapping: %w", err) } return mapping, nil } // InternalToChain resolves an internal platform address to the corresponding // on-chain mapping. func (s *TranslateService) InternalToChain(ctx context.Context, internalAddr string) (*entity.AddressMapping, error) { mapping, err := s.repo.FindByInternalAddress(ctx, internalAddr) if err != nil { return nil, fmt.Errorf("repository lookup failed: %w", err) } return mapping, nil } // ChainToInternal resolves an on-chain address (with chain type) to the // corresponding internal platform mapping. func (s *TranslateService) ChainToInternal(ctx context.Context, chain, chainAddr string) (*entity.AddressMapping, error) { mapping, err := s.repo.FindByChainAddress(ctx, chain, chainAddr) if err != nil { return nil, fmt.Errorf("repository lookup failed: %w", err) } return mapping, nil } // GetByUserID returns all address mappings belonging to the specified user. func (s *TranslateService) GetByUserID(ctx context.Context, userID string) ([]*entity.AddressMapping, error) { mappings, err := s.repo.FindByUserID(ctx, userID) if err != nil { return nil, fmt.Errorf("repository lookup failed: %w", err) } return mappings, nil } // DeleteMapping removes an address mapping by its ID. func (s *TranslateService) DeleteMapping(ctx context.Context, id string) error { if err := s.repo.Delete(ctx, id); err != nil { return fmt.Errorf("failed to delete mapping: %w", err) } return nil }