159 lines
6.0 KiB
Go
159 lines
6.0 KiB
Go
package client
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/tech/sendico/pkg/merrors"
|
|
ledgerv1 "github.com/tech/sendico/pkg/proto/ledger/v1"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/credentials"
|
|
"google.golang.org/grpc/credentials/insecure"
|
|
)
|
|
|
|
// Client exposes typed helpers around the ledger gRPC API.
|
|
type Client interface {
|
|
CreateAccount(ctx context.Context, req *ledgerv1.CreateAccountRequest) (*ledgerv1.CreateAccountResponse, error)
|
|
ListAccounts(ctx context.Context, req *ledgerv1.ListAccountsRequest) (*ledgerv1.ListAccountsResponse, error)
|
|
PostCreditWithCharges(ctx context.Context, req *ledgerv1.PostCreditRequest) (*ledgerv1.PostResponse, error)
|
|
PostDebitWithCharges(ctx context.Context, req *ledgerv1.PostDebitRequest) (*ledgerv1.PostResponse, error)
|
|
TransferInternal(ctx context.Context, req *ledgerv1.TransferRequest) (*ledgerv1.PostResponse, error)
|
|
ApplyFXWithCharges(ctx context.Context, req *ledgerv1.FXRequest) (*ledgerv1.PostResponse, error)
|
|
|
|
GetBalance(ctx context.Context, req *ledgerv1.GetBalanceRequest) (*ledgerv1.BalanceResponse, error)
|
|
GetJournalEntry(ctx context.Context, req *ledgerv1.GetEntryRequest) (*ledgerv1.JournalEntryResponse, error)
|
|
GetStatement(ctx context.Context, req *ledgerv1.GetStatementRequest) (*ledgerv1.StatementResponse, error)
|
|
|
|
Close() error
|
|
}
|
|
|
|
type grpcLedgerClient interface {
|
|
CreateAccount(ctx context.Context, in *ledgerv1.CreateAccountRequest, opts ...grpc.CallOption) (*ledgerv1.CreateAccountResponse, error)
|
|
ListAccounts(ctx context.Context, in *ledgerv1.ListAccountsRequest, opts ...grpc.CallOption) (*ledgerv1.ListAccountsResponse, error)
|
|
PostCreditWithCharges(ctx context.Context, in *ledgerv1.PostCreditRequest, opts ...grpc.CallOption) (*ledgerv1.PostResponse, error)
|
|
PostDebitWithCharges(ctx context.Context, in *ledgerv1.PostDebitRequest, opts ...grpc.CallOption) (*ledgerv1.PostResponse, error)
|
|
TransferInternal(ctx context.Context, in *ledgerv1.TransferRequest, opts ...grpc.CallOption) (*ledgerv1.PostResponse, error)
|
|
ApplyFXWithCharges(ctx context.Context, in *ledgerv1.FXRequest, opts ...grpc.CallOption) (*ledgerv1.PostResponse, error)
|
|
GetBalance(ctx context.Context, in *ledgerv1.GetBalanceRequest, opts ...grpc.CallOption) (*ledgerv1.BalanceResponse, error)
|
|
GetJournalEntry(ctx context.Context, in *ledgerv1.GetEntryRequest, opts ...grpc.CallOption) (*ledgerv1.JournalEntryResponse, error)
|
|
GetStatement(ctx context.Context, in *ledgerv1.GetStatementRequest, opts ...grpc.CallOption) (*ledgerv1.StatementResponse, error)
|
|
}
|
|
|
|
type ledgerClient struct {
|
|
cfg Config
|
|
conn *grpc.ClientConn
|
|
client grpcLedgerClient
|
|
}
|
|
|
|
// New dials the ledger endpoint and returns a ready client.
|
|
func New(ctx context.Context, cfg Config, opts ...grpc.DialOption) (Client, error) {
|
|
cfg.setDefaults()
|
|
if strings.TrimSpace(cfg.Address) == "" {
|
|
return nil, merrors.InvalidArgument("ledger: address is required")
|
|
}
|
|
|
|
dialCtx, cancel := context.WithTimeout(ctx, cfg.DialTimeout)
|
|
defer cancel()
|
|
|
|
dialOpts := make([]grpc.DialOption, 0, len(opts)+1)
|
|
dialOpts = append(dialOpts, opts...)
|
|
|
|
if cfg.Insecure {
|
|
dialOpts = append(dialOpts, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
|
} else {
|
|
dialOpts = append(dialOpts, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})))
|
|
}
|
|
|
|
conn, err := grpc.DialContext(dialCtx, cfg.Address, dialOpts...)
|
|
if err != nil {
|
|
return nil, merrors.InternalWrap(err, fmt.Sprintf("ledger: dial %s", cfg.Address))
|
|
}
|
|
|
|
return &ledgerClient{
|
|
cfg: cfg,
|
|
conn: conn,
|
|
client: ledgerv1.NewLedgerServiceClient(conn),
|
|
}, nil
|
|
}
|
|
|
|
// NewWithClient injects a pre-built ledger client (useful for tests).
|
|
func NewWithClient(cfg Config, lc grpcLedgerClient) Client {
|
|
cfg.setDefaults()
|
|
return &ledgerClient{
|
|
cfg: cfg,
|
|
client: lc,
|
|
}
|
|
}
|
|
|
|
func (c *ledgerClient) Close() error {
|
|
if c.conn != nil {
|
|
return c.conn.Close()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c *ledgerClient) CreateAccount(ctx context.Context, req *ledgerv1.CreateAccountRequest) (*ledgerv1.CreateAccountResponse, error) {
|
|
ctx, cancel := c.callContext(ctx)
|
|
defer cancel()
|
|
return c.client.CreateAccount(ctx, req)
|
|
}
|
|
|
|
func (c *ledgerClient) ListAccounts(ctx context.Context, req *ledgerv1.ListAccountsRequest) (*ledgerv1.ListAccountsResponse, error) {
|
|
ctx, cancel := c.callContext(ctx)
|
|
defer cancel()
|
|
return c.client.ListAccounts(ctx, req)
|
|
}
|
|
|
|
func (c *ledgerClient) PostCreditWithCharges(ctx context.Context, req *ledgerv1.PostCreditRequest) (*ledgerv1.PostResponse, error) {
|
|
ctx, cancel := c.callContext(ctx)
|
|
defer cancel()
|
|
return c.client.PostCreditWithCharges(ctx, req)
|
|
}
|
|
|
|
func (c *ledgerClient) PostDebitWithCharges(ctx context.Context, req *ledgerv1.PostDebitRequest) (*ledgerv1.PostResponse, error) {
|
|
ctx, cancel := c.callContext(ctx)
|
|
defer cancel()
|
|
return c.client.PostDebitWithCharges(ctx, req)
|
|
}
|
|
|
|
func (c *ledgerClient) TransferInternal(ctx context.Context, req *ledgerv1.TransferRequest) (*ledgerv1.PostResponse, error) {
|
|
ctx, cancel := c.callContext(ctx)
|
|
defer cancel()
|
|
return c.client.TransferInternal(ctx, req)
|
|
}
|
|
|
|
func (c *ledgerClient) ApplyFXWithCharges(ctx context.Context, req *ledgerv1.FXRequest) (*ledgerv1.PostResponse, error) {
|
|
ctx, cancel := c.callContext(ctx)
|
|
defer cancel()
|
|
return c.client.ApplyFXWithCharges(ctx, req)
|
|
}
|
|
|
|
func (c *ledgerClient) GetBalance(ctx context.Context, req *ledgerv1.GetBalanceRequest) (*ledgerv1.BalanceResponse, error) {
|
|
ctx, cancel := c.callContext(ctx)
|
|
defer cancel()
|
|
return c.client.GetBalance(ctx, req)
|
|
}
|
|
|
|
func (c *ledgerClient) GetJournalEntry(ctx context.Context, req *ledgerv1.GetEntryRequest) (*ledgerv1.JournalEntryResponse, error) {
|
|
ctx, cancel := c.callContext(ctx)
|
|
defer cancel()
|
|
return c.client.GetJournalEntry(ctx, req)
|
|
}
|
|
|
|
func (c *ledgerClient) GetStatement(ctx context.Context, req *ledgerv1.GetStatementRequest) (*ledgerv1.StatementResponse, error) {
|
|
ctx, cancel := c.callContext(ctx)
|
|
defer cancel()
|
|
return c.client.GetStatement(ctx, req)
|
|
}
|
|
|
|
func (c *ledgerClient) callContext(ctx context.Context) (context.Context, context.CancelFunc) {
|
|
timeout := c.cfg.CallTimeout
|
|
if timeout <= 0 {
|
|
timeout = 3 * time.Second
|
|
}
|
|
return context.WithTimeout(ctx, timeout)
|
|
}
|