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 }