package service import ( "context" "errors" "fmt" "hash-of-wisdom/internal/pow/challenge" "hash-of-wisdom/internal/quotes" ) var ( ErrResourceRequired = errors.New("resource is required") ErrUnsupportedResource = errors.New("unsupported resource") ErrSolutionRequired = errors.New("solution is required") ErrInvalidChallenge = errors.New("invalid challenge") ErrInvalidSolution = errors.New("invalid proof of work solution") ) type ChallengeGenerator interface { GenerateChallenge() (*challenge.Challenge, error) } type ChallengeVerifier interface { VerifyChallenge(ch *challenge.Challenge) error } type QuoteService interface { GetRandomQuote(ctx context.Context) (*quotes.Quote, error) } type WisdomService struct { challengeGenerator ChallengeGenerator challengeVerifier ChallengeVerifier quoteService QuoteService } func NewWisdomService( generator ChallengeGenerator, verifier ChallengeVerifier, quoteService QuoteService, ) *WisdomService { return &WisdomService{ challengeGenerator: generator, challengeVerifier: verifier, quoteService: quoteService, } } func (s *WisdomService) GenerateChallenge(ctx context.Context, resource string) (*challenge.Challenge, error) { if resource == "" { return nil, ErrResourceRequired } if resource != "quotes" { return nil, ErrUnsupportedResource } ch, err := s.challengeGenerator.GenerateChallenge() if err != nil { return nil, fmt.Errorf("failed to generate challenge: %w", err) } return ch, nil } func (s *WisdomService) VerifySolution(ctx context.Context, solution *challenge.Solution) error { if solution == nil { return ErrSolutionRequired } // Verify challenge authenticity and expiration if err := s.challengeVerifier.VerifyChallenge(&solution.Challenge); err != nil { return fmt.Errorf("%w: %v", ErrInvalidChallenge, err) } // Verify PoW solution if !solution.Verify() { return ErrInvalidSolution } return nil } func (s *WisdomService) GetQuote(ctx context.Context) (*quotes.Quote, error) { return s.quoteService.GetRandomQuote(ctx) }