Skip to content

Tech: GetAccountBalances #785 #788

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
May 5, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions api/client/GetAccountBalances/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package main

import (
"context"
"fmt"

log "github.com/sirupsen/logrus"
"github.com/spf13/viper"
rpc_model "github.com/zoobc/zoobc-core/common/model"
rpc_service "github.com/zoobc/zoobc-core/common/service"
"github.com/zoobc/zoobc-core/common/util"
"google.golang.org/grpc"
)

func main() {
var apiRPCPort int
if err := util.LoadConfig("../../../resource", "config", "toml"); err != nil {
log.Fatal(err)
} else {
apiRPCPort = viper.GetInt("apiRPCPort")
if apiRPCPort == 0 {
apiRPCPort = 8080
}
}

conn, err := grpc.Dial(fmt.Sprintf(":%d", apiRPCPort), grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %s", err)
}
defer conn.Close()

c := rpc_service.NewAccountBalanceServiceClient(conn)

response, err := c.GetAccountBalances(context.Background(), &rpc_model.GetAccountBalancesRequest{
AccountAddresses: []string{
"OnEYzI-EMV6UTfoUEzpQUjkSlnqB82-SyRN7469lJTWH",
"BCZEGOb3WNx3fDOVf9ZS4EjvOIv_UeW4TVBQJ_6tHKlE",
"iSJt3H8wFOzlWKsy_UoEWF_OjF6oymHMqthyUMDKSyxb",
},
})

if err != nil {
log.Fatalf("error calling rpc_service.GetAccountBalance: %s", err)
}

log.Printf("response from remote rpc_service.GetBlockByID(): %s", response)

}
18 changes: 13 additions & 5 deletions api/handler/accountBalanceHandler.go
Original file line number Diff line number Diff line change
@@ -5,11 +5,15 @@ import (

"github.com/zoobc/zoobc-core/api/service"
"github.com/zoobc/zoobc-core/common/model"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

type AccountBalanceHandler struct {
Service service.AccountBalanceServiceInterface
}
type (
AccountBalanceHandler struct {
Service service.AccountBalanceServiceInterface
}
)

func (abh *AccountBalanceHandler) GetAccountBalance(ctx context.Context,
request *model.GetAccountBalanceRequest) (*model.GetAccountBalanceResponse, error) {
@@ -22,6 +26,10 @@ func (abh *AccountBalanceHandler) GetAccountBalance(ctx context.Context,

func (abh *AccountBalanceHandler) GetAccountBalances(ctx context.Context,
request *model.GetAccountBalancesRequest) (*model.GetAccountBalancesResponse, error) {
// todo: implement this after have filter
return nil, nil

if len(request.AccountAddresses) == 0 {
return nil, status.Error(codes.InvalidArgument, "At least 1 address is required")
}

return abh.Service.GetAccountBalances(request)
}
45 changes: 40 additions & 5 deletions api/service/accountBalanceApiService.go
Original file line number Diff line number Diff line change
@@ -12,19 +12,20 @@ import (
type (
AccountBalanceServiceInterface interface {
GetAccountBalance(request *model.GetAccountBalanceRequest) (*model.GetAccountBalanceResponse, error)
GetAccountBalances(request *model.GetAccountBalancesRequest) (*model.GetAccountBalancesResponse, error)
}

AccountBalanceService struct {
AccountBalanceQuery query.AccountBalanceQueryInterface
Executor query.ExecutorInterface
AccountBalanceQuery *query.AccountBalanceQuery
QueryExecutor query.ExecutorInterface
}
)

func NewAccountBalanceService(executor query.ExecutorInterface,
accountBalanceQuery query.AccountBalanceQueryInterface) *AccountBalanceService {
accountBalanceQuery *query.AccountBalanceQuery) *AccountBalanceService {
return &AccountBalanceService{
AccountBalanceQuery: accountBalanceQuery,
Executor: executor,
QueryExecutor: executor,
}
}

@@ -36,7 +37,7 @@ func (abs *AccountBalanceService) GetAccountBalance(request *model.GetAccountBal
)

qry, args := abs.AccountBalanceQuery.GetAccountBalanceByAccountAddress(request.AccountAddress)
row, _ = abs.Executor.ExecuteSelectRow(qry, false, args...)
row, _ = abs.QueryExecutor.ExecuteSelectRow(qry, false, args...)
err = abs.AccountBalanceQuery.Scan(&accountBalance, row)
if err != nil {
if err != sql.ErrNoRows {
@@ -50,3 +51,37 @@ func (abs *AccountBalanceService) GetAccountBalance(request *model.GetAccountBal
AccountBalance: &accountBalance,
}, nil
}

func (abs *AccountBalanceService) GetAccountBalances(
request *model.GetAccountBalancesRequest,
) (*model.GetAccountBalancesResponse, error) {
var (
accountBalances []*model.AccountBalance
caseQ = query.NewCaseQuery()
rows *sql.Rows
err error
)

caseQ.Select(abs.AccountBalanceQuery.TableName, abs.AccountBalanceQuery.Fields...)
var accountAddresses []interface{}
for _, v := range request.AccountAddresses {
accountAddresses = append(accountAddresses, v)
}
caseQ.And(caseQ.In("account_address", accountAddresses...))

selectQ, args := caseQ.Build()
rows, err = abs.QueryExecutor.ExecuteSelect(selectQ, false, args...)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}
defer rows.Close()

accountBalances, err = abs.AccountBalanceQuery.BuildModel([]*model.AccountBalance{}, rows)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}

return &model.GetAccountBalancesResponse{
AccountBalances: accountBalances,
}, nil
}
89 changes: 62 additions & 27 deletions api/service/accountBalanceApiService_test.go
Original file line number Diff line number Diff line change
@@ -56,10 +56,41 @@ func (*mockExecutorGetAccountBalanceNotFound) ExecuteSelectRow(qe string, _ bool
return row, nil
}

func TestNewAccountBalanceService(t *testing.T) {
type args struct {
executor query.ExecutorInterface
accountBalanceQuery *query.AccountBalanceQuery
}
tests := []struct {
name string
args args
want *AccountBalanceService
}{
{
name: "NewAccountBalanceService:success",
args: args{
executor: nil,
accountBalanceQuery: nil,
},
want: &AccountBalanceService{
AccountBalanceQuery: nil,
QueryExecutor: nil,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := NewAccountBalanceService(tt.args.executor, tt.args.accountBalanceQuery); !reflect.DeepEqual(got, tt.want) {
t.Errorf("NewAccountBalanceService() = %v, want %v", got, tt.want)
}
})
}
}

func TestAccountBalanceService_GetAccountBalance(t *testing.T) {
type fields struct {
AccountBalanceQuery query.AccountBalanceQueryInterface
Executor query.ExecutorInterface
AccountBalanceQuery *query.AccountBalanceQuery
QueryExecutor query.ExecutorInterface
}
type args struct {
request *model.GetAccountBalanceRequest
@@ -75,7 +106,7 @@ func TestAccountBalanceService_GetAccountBalance(t *testing.T) {
name: "GetAccountBalance:fail",
fields: fields{
AccountBalanceQuery: mockAccountBalanceQuery,
Executor: &mockExecutorGetAccountBalanceFail{},
QueryExecutor: &mockExecutorGetAccountBalanceFail{},
},
args: args{request: &model.GetAccountBalanceRequest{
AccountAddress: "BCZ000000000000",
@@ -87,7 +118,7 @@ func TestAccountBalanceService_GetAccountBalance(t *testing.T) {
name: "GetAccountBalance:notFound",
fields: fields{
AccountBalanceQuery: mockAccountBalanceQuery,
Executor: &mockExecutorGetAccountBalanceNotFound{},
QueryExecutor: &mockExecutorGetAccountBalanceNotFound{},
},
args: args{request: &model.GetAccountBalanceRequest{
AccountAddress: "BCZ000000000000",
@@ -99,7 +130,7 @@ func TestAccountBalanceService_GetAccountBalance(t *testing.T) {
name: "GetAccountBalance:success",
fields: fields{
AccountBalanceQuery: mockAccountBalanceQuery,
Executor: &mockExecutorGetAccountBalanceSuccess{},
QueryExecutor: &mockExecutorGetAccountBalanceSuccess{},
},
args: args{request: &model.GetAccountBalanceRequest{
AccountAddress: "BCZ000000000000",
@@ -121,46 +152,50 @@ func TestAccountBalanceService_GetAccountBalance(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
abs := &AccountBalanceService{
AccountBalanceQuery: tt.fields.AccountBalanceQuery,
Executor: tt.fields.Executor,
QueryExecutor: tt.fields.QueryExecutor,
}
got, err := abs.GetAccountBalance(tt.args.request)
if (err != nil) != tt.wantErr {
t.Errorf("GetAccountBalance() error = %v, wantErr %v", err, tt.wantErr)
t.Errorf("AccountBalanceService.GetAccountBalance() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("GetAccountBalance() got = %v, want %v", got, tt.want)
t.Errorf("AccountBalanceService.GetAccountBalance() = %v, want %v", got, tt.want)
}
})
}
}

func TestNewAccountBalanceService(t *testing.T) {
func TestAccountBalanceService_GetAccountBalances(t *testing.T) {
type fields struct {
AccountBalanceQuery *query.AccountBalanceQuery
QueryExecutor query.ExecutorInterface
}
type args struct {
executor query.ExecutorInterface
accountBalanceQuery query.AccountBalanceQueryInterface
request *model.GetAccountBalancesRequest
}
tests := []struct {
name string
args args
want *AccountBalanceService
name string
fields fields
args args
want *model.GetAccountBalancesResponse
wantErr bool
}{
{
name: "NewAccountBalanceService:success",
args: args{
executor: nil,
accountBalanceQuery: nil,
},
want: &AccountBalanceService{
AccountBalanceQuery: nil,
Executor: nil,
},
},
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := NewAccountBalanceService(tt.args.executor, tt.args.accountBalanceQuery); !reflect.DeepEqual(got, tt.want) {
t.Errorf("NewAccountBalanceService() = %v, want %v", got, tt.want)
abs := &AccountBalanceService{
AccountBalanceQuery: tt.fields.AccountBalanceQuery,
QueryExecutor: tt.fields.QueryExecutor,
}
got, err := abs.GetAccountBalances(tt.args.request)
if (err != nil) != tt.wantErr {
t.Errorf("AccountBalanceService.GetAccountBalances() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("AccountBalanceService.GetAccountBalances() = %v, want %v", got, tt.want)
}
})
}
Loading