github.com/s7techlab/cckit@v0.10.5/examples/token/service/allowance/allowance.go (about)

     1  package allowance
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	"github.com/s7techlab/cckit/examples/token/service/balance"
     8  	"github.com/s7techlab/cckit/router"
     9  )
    10  
    11  var (
    12  	ErrOwnerOnly             = errors.New(`owner only`)
    13  	ErrAllowanceInsufficient = errors.New(`allowance insufficient`)
    14  )
    15  
    16  type Service struct {
    17  	balance *balance.Service
    18  }
    19  
    20  func NewService(balance *balance.Service) *Service {
    21  	return &Service{
    22  		balance: balance,
    23  	}
    24  }
    25  
    26  func (s *Service) GetAllowance(ctx router.Context, req *AllowanceRequest) (*Allowance, error) {
    27  	if err := router.ValidateRequest(req); err != nil {
    28  		return nil, err
    29  	}
    30  
    31  	allowance, err := NewStore(ctx).Get(req.OwnerAddress, req.SpenderAddress, req.Token)
    32  	if err != nil {
    33  		return nil, err
    34  	}
    35  
    36  	return allowance, nil
    37  }
    38  
    39  func (s *Service) Approve(ctx router.Context, req *ApproveRequest) (*Allowance, error) {
    40  	if err := router.ValidateRequest(req); err != nil {
    41  		return nil, err
    42  	}
    43  
    44  	invokerAddress, err := s.balance.Account.GetInvokerAddress(ctx, nil)
    45  	if err != nil {
    46  		return nil, fmt.Errorf(`get invoker address: %w`, err)
    47  	}
    48  
    49  	if invokerAddress.Address != req.OwnerAddress {
    50  		return nil, ErrOwnerOnly
    51  	}
    52  
    53  	allowance, err := NewStore(ctx).Set(req.OwnerAddress, req.SpenderAddress, req.Token, req.Amount)
    54  	if err != nil {
    55  		return nil, err
    56  	}
    57  
    58  	if err = Event(ctx).Set(&Approved{
    59  		OwnerAddress:   req.OwnerAddress,
    60  		SpenderAddress: req.SpenderAddress,
    61  		Amount:         req.Amount,
    62  	}); err != nil {
    63  		return nil, err
    64  	}
    65  
    66  	return allowance, nil
    67  }
    68  
    69  func (s *Service) TransferFrom(ctx router.Context, req *TransferFromRequest) (*TransferFromResponse, error) {
    70  	if err := router.ValidateRequest(req); err != nil {
    71  		return nil, err
    72  	}
    73  
    74  	spenderAddress, err := s.balance.Account.GetInvokerAddress(ctx, nil)
    75  	if err != nil {
    76  		return nil, err
    77  	}
    78  
    79  	allowance, err := NewStore(ctx).Get(req.OwnerAddress, spenderAddress.Address, req.Token)
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  
    84  	if allowance.Amount < req.Amount {
    85  		return nil, fmt.Errorf(`request trasfer amount=%d, allowance=%d: %w`,
    86  			req.Amount, allowance.Amount, ErrAllowanceInsufficient)
    87  	}
    88  
    89  	if err = s.balance.Store(ctx).Transfer(req.OwnerAddress, req.RecipientAddress, req.Token, req.Amount); err != nil {
    90  		return nil, err
    91  	}
    92  
    93  	if err = Event(ctx).Set(&TransferredFrom{
    94  		OwnerAddress:     req.OwnerAddress,
    95  		SpenderAddress:   spenderAddress.Address,
    96  		RecipientAddress: req.RecipientAddress,
    97  		Amount:           0,
    98  	}); err != nil {
    99  		return nil, err
   100  	}
   101  
   102  	return &TransferFromResponse{
   103  		OwnerAddress:     req.OwnerAddress,
   104  		RecipientAddress: req.RecipientAddress,
   105  		Amount:           req.Amount,
   106  	}, nil
   107  }