2020-07-10 14:17:51 +00:00
|
|
|
package accounting
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
|
|
|
|
"github.com/nspcc-dev/neofs-api-go/accounting"
|
|
|
|
"github.com/nspcc-dev/neofs-api-go/decimal"
|
2020-07-24 13:54:03 +00:00
|
|
|
"github.com/nspcc-dev/neofs-node/pkg/morph/client/balance/wrapper"
|
|
|
|
"github.com/nspcc-dev/neofs-node/pkg/network/transport/grpc"
|
|
|
|
libgrpc "github.com/nspcc-dev/neofs-node/pkg/network/transport/grpc"
|
2020-07-10 14:17:51 +00:00
|
|
|
"google.golang.org/grpc/codes"
|
|
|
|
"google.golang.org/grpc/status"
|
|
|
|
)
|
|
|
|
|
|
|
|
type (
|
|
|
|
// Service is an interface of the server of Accounting service.
|
|
|
|
Service interface {
|
|
|
|
grpc.Service
|
|
|
|
accounting.AccountingServer
|
|
|
|
}
|
|
|
|
|
2020-07-24 13:54:03 +00:00
|
|
|
// ContractClient represents the client of Balance contract.
|
|
|
|
//
|
|
|
|
// It is a type alias of the pointer to
|
|
|
|
// github.com/nspcc-dev/neofs-node/pkg/morph/client/balance/wrapper.Wrapper.
|
|
|
|
ContractClient = *wrapper.Wrapper
|
|
|
|
|
2020-07-10 14:17:51 +00:00
|
|
|
// Params groups the parameters of Accounting service server's constructor.
|
|
|
|
Params struct {
|
2020-07-24 13:54:03 +00:00
|
|
|
ContractClient ContractClient
|
2020-07-10 14:17:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
accService struct {
|
2020-07-24 13:54:03 +00:00
|
|
|
contractClient ContractClient
|
2020-07-10 14:17:51 +00:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2020-07-24 13:54:03 +00:00
|
|
|
var requestVerifyFunc = libgrpc.VerifyRequestWithSignatures
|
2020-07-10 14:17:51 +00:00
|
|
|
|
|
|
|
// New is an Accounting service server's constructor.
|
2020-07-24 13:54:03 +00:00
|
|
|
//
|
|
|
|
// If Balance contract client is nil,
|
|
|
|
// wrapper.ErrNilWrapper is returned.
|
2020-07-10 14:17:51 +00:00
|
|
|
func New(p Params) (Service, error) {
|
2020-07-24 13:54:03 +00:00
|
|
|
if p.ContractClient == nil {
|
|
|
|
return nil, wrapper.ErrNilWrapper
|
|
|
|
}
|
|
|
|
|
2020-07-10 14:17:51 +00:00
|
|
|
return &accService{
|
2020-07-24 13:54:03 +00:00
|
|
|
contractClient: p.ContractClient,
|
2020-07-10 14:17:51 +00:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (accService) Name() string { return "AccountingService" }
|
|
|
|
|
|
|
|
func (s accService) Register(g *grpc.Server) { accounting.RegisterAccountingServer(g, s) }
|
|
|
|
|
|
|
|
func (s accService) Balance(ctx context.Context, req *accounting.BalanceRequest) (*accounting.BalanceResponse, error) {
|
|
|
|
// verify request structure
|
|
|
|
if err := requestVerifyFunc(req); err != nil {
|
|
|
|
return nil, status.Error(codes.InvalidArgument, err.Error())
|
|
|
|
}
|
|
|
|
|
2020-07-24 13:54:03 +00:00
|
|
|
// get the amount of funds in client's account
|
|
|
|
fundsAmount, err := s.contractClient.BalanceOf(req.GetOwnerID())
|
2020-07-10 14:17:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, status.Error(codes.Aborted, err.Error())
|
|
|
|
}
|
|
|
|
|
2020-07-24 13:54:03 +00:00
|
|
|
// get decimals precision of currency transactions
|
2020-07-10 14:17:51 +00:00
|
|
|
|
|
|
|
// TODO: Reconsider the approach of getting decimals.
|
|
|
|
//
|
|
|
|
// Decimals value does not seem to be frequently changing.
|
|
|
|
// In this case service can work in static decimals mode and
|
|
|
|
// the value can be received once to facilitate call flow.
|
|
|
|
//
|
|
|
|
// In a true dynamic value installation it is advisable to get
|
|
|
|
// a balance with decimals through a single call. Variations:
|
|
|
|
// - add decimal value stack parameter of balanceOf method;
|
|
|
|
// - create a new method entitled smth like balanceWithDecimals.
|
2020-07-24 13:54:03 +00:00
|
|
|
decimals, err := s.contractClient.Decimals()
|
2020-07-10 14:17:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, status.Error(codes.Aborted, err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
res := new(accounting.BalanceResponse)
|
|
|
|
res.Balance = decimal.NewWithPrecision(
|
2020-07-24 13:54:03 +00:00
|
|
|
fundsAmount,
|
|
|
|
decimals,
|
2020-07-10 14:17:51 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
return res, nil
|
|
|
|
}
|