package client import ( "context" "strings" "time" "github.com/tech/sendico/pkg/merrors" mntxv1 "github.com/tech/sendico/pkg/proto/gateway/mntx/v1" "go.uber.org/zap" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) // Client wraps the Monetix gateway gRPC API. type Client interface { CreateCardPayout(ctx context.Context, req *mntxv1.CardPayoutRequest) (*mntxv1.CardPayoutResponse, error) CreateCardTokenPayout(ctx context.Context, req *mntxv1.CardTokenPayoutRequest) (*mntxv1.CardTokenPayoutResponse, error) GetCardPayoutStatus(ctx context.Context, req *mntxv1.GetCardPayoutStatusRequest) (*mntxv1.GetCardPayoutStatusResponse, error) Close() error } type gatewayClient struct { conn *grpc.ClientConn client mntxv1.MntxGatewayServiceClient cfg Config logger *zap.Logger } // New dials the Monetix gateway. func New(ctx context.Context, cfg Config, opts ...grpc.DialOption) (Client, error) { cfg.setDefaults() if strings.TrimSpace(cfg.Address) == "" { return nil, merrors.InvalidArgument("mntx: address is required") } dialCtx, cancel := context.WithTimeout(ctx, cfg.DialTimeout) defer cancel() dialOpts := make([]grpc.DialOption, 0, len(opts)+1) dialOpts = append(dialOpts, grpc.WithTransportCredentials(insecure.NewCredentials())) dialOpts = append(dialOpts, opts...) conn, err := grpc.DialContext(dialCtx, cfg.Address, dialOpts...) if err != nil { return nil, merrors.Internal("mntx: dial failed: " + err.Error()) } return &gatewayClient{ conn: conn, client: mntxv1.NewMntxGatewayServiceClient(conn), cfg: cfg, logger: cfg.Logger, }, nil } func (g *gatewayClient) Close() error { if g.conn != nil { return g.conn.Close() } return nil } func (g *gatewayClient) callContext(ctx context.Context, method string) (context.Context, context.CancelFunc) { if ctx == nil { ctx = context.Background() } timeout := g.cfg.CallTimeout if timeout <= 0 { timeout = 5 * time.Second } fields := []zap.Field{ zap.String("method", method), zap.Duration("timeout", timeout), } if deadline, ok := ctx.Deadline(); ok { fields = append(fields, zap.Time("parent_deadline", deadline), zap.Duration("parent_deadline_in", time.Until(deadline))) } g.logger.Info("Mntx gateway client call timeout applied", fields...) return context.WithTimeout(ctx, timeout) } func (g *gatewayClient) CreateCardPayout(ctx context.Context, req *mntxv1.CardPayoutRequest) (*mntxv1.CardPayoutResponse, error) { ctx, cancel := g.callContext(ctx, "CreateCardPayout") defer cancel() return g.client.CreateCardPayout(ctx, req) } func (g *gatewayClient) CreateCardTokenPayout(ctx context.Context, req *mntxv1.CardTokenPayoutRequest) (*mntxv1.CardTokenPayoutResponse, error) { ctx, cancel := g.callContext(ctx, "CreateCardTokenPayout") defer cancel() return g.client.CreateCardTokenPayout(ctx, req) } func (g *gatewayClient) GetCardPayoutStatus(ctx context.Context, req *mntxv1.GetCardPayoutStatusRequest) (*mntxv1.GetCardPayoutStatusResponse, error) { ctx, cancel := g.callContext(ctx, "GetCardPayoutStatus") defer cancel() return g.client.GetCardPayoutStatus(ctx, req) }