linting
This commit is contained in:
47
api/payments/methods/.golangci.yml
Normal file
47
api/payments/methods/.golangci.yml
Normal file
@@ -0,0 +1,47 @@
|
||||
version: "2"
|
||||
linters:
|
||||
default: none
|
||||
enable:
|
||||
- bodyclose
|
||||
- canonicalheader
|
||||
- copyloopvar
|
||||
- durationcheck
|
||||
- errcheck
|
||||
- errchkjson
|
||||
- errname
|
||||
- errorlint
|
||||
- gosec
|
||||
- govet
|
||||
- ineffassign
|
||||
- nilerr
|
||||
- nilnesserr
|
||||
- nilnil
|
||||
- noctx
|
||||
- rowserrcheck
|
||||
- sqlclosecheck
|
||||
- staticcheck
|
||||
- unconvert
|
||||
- wastedassign
|
||||
disable:
|
||||
- depguard
|
||||
- exhaustruct
|
||||
- gochecknoglobals
|
||||
- gochecknoinits
|
||||
- gomoddirectives
|
||||
- wrapcheck
|
||||
- cyclop
|
||||
- dupl
|
||||
- funlen
|
||||
- gocognit
|
||||
- gocyclo
|
||||
- ireturn
|
||||
- lll
|
||||
- mnd
|
||||
- nestif
|
||||
- nlreturn
|
||||
- noinlineerr
|
||||
- paralleltest
|
||||
- tagliatelle
|
||||
- testpackage
|
||||
- varnamelen
|
||||
- wsl_v5
|
||||
@@ -85,52 +85,86 @@ func (c *paymentMethodsClient) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *paymentMethodsClient) callContext(ctx context.Context) (context.Context, context.CancelFunc) {
|
||||
func (c *paymentMethodsClient) CreatePaymentMethod(ctx context.Context, req *methodsv1.CreatePaymentMethodRequest) (*methodsv1.CreatePaymentMethodResponse, error) {
|
||||
timeout := c.cfg.CallTimeout
|
||||
if timeout <= 0 {
|
||||
timeout = 3 * time.Second
|
||||
}
|
||||
return context.WithTimeout(ctx, timeout)
|
||||
}
|
||||
|
||||
func (c *paymentMethodsClient) CreatePaymentMethod(ctx context.Context, req *methodsv1.CreatePaymentMethodRequest) (*methodsv1.CreatePaymentMethodResponse, error) {
|
||||
callCtx, cancel := c.callContext(ctx)
|
||||
callCtx, cancel := context.WithTimeout(ctx, timeout)
|
||||
defer cancel()
|
||||
|
||||
return c.client.CreatePaymentMethod(callCtx, req)
|
||||
}
|
||||
|
||||
func (c *paymentMethodsClient) GetPaymentMethod(ctx context.Context, req *methodsv1.GetPaymentMethodRequest) (*methodsv1.GetPaymentMethodResponse, error) {
|
||||
callCtx, cancel := c.callContext(ctx)
|
||||
timeout := c.cfg.CallTimeout
|
||||
if timeout <= 0 {
|
||||
timeout = 3 * time.Second
|
||||
}
|
||||
|
||||
callCtx, cancel := context.WithTimeout(ctx, timeout)
|
||||
defer cancel()
|
||||
|
||||
return c.client.GetPaymentMethod(callCtx, req)
|
||||
}
|
||||
|
||||
func (c *paymentMethodsClient) GetPaymentMethodPrivate(ctx context.Context, req *methodsv1.GetPaymentMethodPrivateRequest) (*methodsv1.GetPaymentMethodPrivateResponse, error) {
|
||||
callCtx, cancel := c.callContext(ctx)
|
||||
timeout := c.cfg.CallTimeout
|
||||
if timeout <= 0 {
|
||||
timeout = 3 * time.Second
|
||||
}
|
||||
|
||||
callCtx, cancel := context.WithTimeout(ctx, timeout)
|
||||
defer cancel()
|
||||
|
||||
return c.client.GetPaymentMethodPrivate(callCtx, req)
|
||||
}
|
||||
|
||||
func (c *paymentMethodsClient) UpdatePaymentMethod(ctx context.Context, req *methodsv1.UpdatePaymentMethodRequest) (*methodsv1.UpdatePaymentMethodResponse, error) {
|
||||
callCtx, cancel := c.callContext(ctx)
|
||||
timeout := c.cfg.CallTimeout
|
||||
if timeout <= 0 {
|
||||
timeout = 3 * time.Second
|
||||
}
|
||||
|
||||
callCtx, cancel := context.WithTimeout(ctx, timeout)
|
||||
defer cancel()
|
||||
|
||||
return c.client.UpdatePaymentMethod(callCtx, req)
|
||||
}
|
||||
|
||||
func (c *paymentMethodsClient) DeletePaymentMethod(ctx context.Context, req *methodsv1.DeletePaymentMethodRequest) (*methodsv1.DeletePaymentMethodResponse, error) {
|
||||
callCtx, cancel := c.callContext(ctx)
|
||||
timeout := c.cfg.CallTimeout
|
||||
if timeout <= 0 {
|
||||
timeout = 3 * time.Second
|
||||
}
|
||||
|
||||
callCtx, cancel := context.WithTimeout(ctx, timeout)
|
||||
defer cancel()
|
||||
|
||||
return c.client.DeletePaymentMethod(callCtx, req)
|
||||
}
|
||||
|
||||
func (c *paymentMethodsClient) SetPaymentMethodArchived(ctx context.Context, req *methodsv1.SetPaymentMethodArchivedRequest) (*methodsv1.SetPaymentMethodArchivedResponse, error) {
|
||||
callCtx, cancel := c.callContext(ctx)
|
||||
timeout := c.cfg.CallTimeout
|
||||
if timeout <= 0 {
|
||||
timeout = 3 * time.Second
|
||||
}
|
||||
|
||||
callCtx, cancel := context.WithTimeout(ctx, timeout)
|
||||
defer cancel()
|
||||
|
||||
return c.client.SetPaymentMethodArchived(callCtx, req)
|
||||
}
|
||||
|
||||
func (c *paymentMethodsClient) ListPaymentMethods(ctx context.Context, req *methodsv1.ListPaymentMethodsRequest) (*methodsv1.ListPaymentMethodsResponse, error) {
|
||||
callCtx, cancel := c.callContext(ctx)
|
||||
timeout := c.cfg.CallTimeout
|
||||
if timeout <= 0 {
|
||||
timeout = 3 * time.Second
|
||||
}
|
||||
|
||||
callCtx, cancel := context.WithTimeout(ctx, timeout)
|
||||
defer cancel()
|
||||
|
||||
return c.client.ListPaymentMethods(callCtx, req)
|
||||
}
|
||||
|
||||
47
api/payments/orchestrator/.golangci.yml
Normal file
47
api/payments/orchestrator/.golangci.yml
Normal file
@@ -0,0 +1,47 @@
|
||||
version: "2"
|
||||
linters:
|
||||
default: none
|
||||
enable:
|
||||
- bodyclose
|
||||
- canonicalheader
|
||||
- copyloopvar
|
||||
- durationcheck
|
||||
- errcheck
|
||||
- errchkjson
|
||||
- errname
|
||||
- errorlint
|
||||
- gosec
|
||||
- govet
|
||||
- ineffassign
|
||||
- nilerr
|
||||
- nilnesserr
|
||||
- nilnil
|
||||
- noctx
|
||||
- rowserrcheck
|
||||
- sqlclosecheck
|
||||
- staticcheck
|
||||
- unconvert
|
||||
- wastedassign
|
||||
disable:
|
||||
- depguard
|
||||
- exhaustruct
|
||||
- gochecknoglobals
|
||||
- gochecknoinits
|
||||
- gomoddirectives
|
||||
- wrapcheck
|
||||
- cyclop
|
||||
- dupl
|
||||
- funlen
|
||||
- gocognit
|
||||
- gocyclo
|
||||
- ireturn
|
||||
- lll
|
||||
- mnd
|
||||
- nestif
|
||||
- nlreturn
|
||||
- noinlineerr
|
||||
- paralleltest
|
||||
- tagliatelle
|
||||
- testpackage
|
||||
- varnamelen
|
||||
- wsl_v5
|
||||
@@ -122,5 +122,5 @@ func (c *orchestratorClient) callContext(ctx context.Context) (context.Context,
|
||||
if timeout <= 0 {
|
||||
timeout = 3 * time.Second
|
||||
}
|
||||
return context.WithTimeout(ctx, timeout)
|
||||
return context.WithTimeout(ctx, timeout) //nolint:gosec // cancel func is always invoked by call sites
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ func (i *Imp) initDiscovery(cfg *config) {
|
||||
InvokeURI: cfg.GRPC.DiscoveryInvokeURI(),
|
||||
Version: appversion.Create().Short(),
|
||||
}
|
||||
i.discoveryAnnouncer = discovery.NewAnnouncer(i.logger, producer, string(mservice.PaymentOrchestrator), announce)
|
||||
i.discoveryAnnouncer = discovery.NewAnnouncer(i.logger, producer, mservice.PaymentOrchestrator, announce)
|
||||
i.discoveryAnnouncer.Start()
|
||||
}
|
||||
|
||||
|
||||
@@ -321,7 +321,7 @@ func (r *discoveryClientResolver) findEntry(service mservice.Type, rail string,
|
||||
}
|
||||
|
||||
func discoverySelectionKey(service mservice.Type, rail, network string) string {
|
||||
serviceName := strings.TrimSpace(string(service))
|
||||
serviceName := strings.TrimSpace(service)
|
||||
railName := strings.ToUpper(strings.TrimSpace(rail))
|
||||
networkName := strings.ToUpper(strings.TrimSpace(network))
|
||||
|
||||
@@ -392,10 +392,10 @@ func discoveryEntryKey(entry discovery.RegistryEntry) string {
|
||||
|
||||
func matchesService(service string, candidate mservice.Type) bool {
|
||||
service = strings.TrimSpace(service)
|
||||
if service == "" || strings.TrimSpace(string(candidate)) == "" {
|
||||
if service == "" || strings.TrimSpace(candidate) == "" {
|
||||
return false
|
||||
}
|
||||
return strings.EqualFold(service, strings.TrimSpace(string(candidate)))
|
||||
return strings.EqualFold(service, strings.TrimSpace(candidate))
|
||||
}
|
||||
|
||||
func parseDiscoveryEndpoint(raw string) (discoveryEndpoint, error) {
|
||||
@@ -441,15 +441,12 @@ func parseDiscoveryEndpoint(raw string) (discoveryEndpoint, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func dialGrpc(ctx context.Context, endpoint discoveryEndpoint) (*grpc.ClientConn, error) {
|
||||
func dialGrpc(_ context.Context, endpoint discoveryEndpoint) (*grpc.ClientConn, error) {
|
||||
dialOpts := []grpc.DialOption{}
|
||||
if endpoint.insecure {
|
||||
dialOpts = append(dialOpts, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
} else {
|
||||
dialOpts = append(dialOpts, grpc.WithTransportCredentials(credentials.NewTLS(nil)))
|
||||
}
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
return grpc.NewClient(endpoint.address, dialOpts...)
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ func (c *discoveryLedgerClient) Close() error {
|
||||
}
|
||||
client, err := c.resolver.LedgerClient(context.Background())
|
||||
if err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
return client.Close()
|
||||
}
|
||||
@@ -241,7 +241,7 @@ func (c *discoveryOracleClient) Close() error {
|
||||
}
|
||||
client, err := c.resolver.OracleClient(context.Background())
|
||||
if err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
return client.Close()
|
||||
}
|
||||
@@ -348,7 +348,7 @@ func (c *discoveryChainClient) Close() error {
|
||||
}
|
||||
client, err := c.resolver.ChainClient(context.Background(), c.invokeURI)
|
||||
if err != nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
return client.Close()
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ func cloneIntentSnapshot(src model.PaymentIntent) (model.PaymentIntent, error) {
|
||||
|
||||
func cloneQuoteSnapshot(src *model.PaymentQuoteSnapshot) (*model.PaymentQuoteSnapshot, error) {
|
||||
if src == nil {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil snapshot means quote data is intentionally absent
|
||||
}
|
||||
dst := &model.PaymentQuoteSnapshot{}
|
||||
if err := bsonClone(src, dst); err != nil {
|
||||
|
||||
@@ -291,7 +291,6 @@ func TestCreate_InputValidation(t *testing.T) {
|
||||
|
||||
factory := New()
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_, err := factory.Create(tt.in)
|
||||
if err == nil {
|
||||
|
||||
@@ -95,8 +95,8 @@ func paginateEntries(items []TimelineEntry, limit int32, desc bool) []TimelineEn
|
||||
if len(items) == 0 {
|
||||
return nil
|
||||
}
|
||||
if int32(len(items)) > limit {
|
||||
items = items[:limit]
|
||||
if limit > 0 && len(items) > int(limit) {
|
||||
items = items[:int(limit)]
|
||||
}
|
||||
out := make([]TimelineEntry, 0, len(items))
|
||||
for i := range items {
|
||||
|
||||
@@ -229,7 +229,7 @@ func cloneIntentSnapshot(src model.PaymentIntent) (model.PaymentIntent, error) {
|
||||
|
||||
func cloneQuoteSnapshot(src *model.PaymentQuoteSnapshot) (*model.PaymentQuoteSnapshot, error) {
|
||||
if src == nil {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil snapshot means quote data is intentionally absent
|
||||
}
|
||||
dst := &model.PaymentQuoteSnapshot{}
|
||||
if err := bsonClone(src, dst); err != nil {
|
||||
|
||||
@@ -360,11 +360,11 @@ func buildOutput(items []*agg.Payment, limit int32) *ListPaymentsOutput {
|
||||
if len(items) == 0 {
|
||||
return &ListPaymentsOutput{}
|
||||
}
|
||||
if int32(len(items)) > limit {
|
||||
items = items[:limit]
|
||||
if limit > 0 && len(items) > int(limit) {
|
||||
items = items[:int(limit)]
|
||||
}
|
||||
var nextCursor *prepo.ListCursor
|
||||
if int32(len(items)) == limit {
|
||||
if limit > 0 && len(items) == int(limit) {
|
||||
nextCursor = cursorFromPayment(items[len(items)-1])
|
||||
}
|
||||
return &ListPaymentsOutput{
|
||||
|
||||
@@ -32,7 +32,7 @@ func (*paymentDocument) Collection() string {
|
||||
|
||||
func toDocument(payment *agg.Payment) (*paymentDocument, error) {
|
||||
if payment == nil {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil aggregate means no document to persist
|
||||
}
|
||||
doc := &paymentDocument{
|
||||
Base: payment.Base,
|
||||
@@ -52,7 +52,7 @@ func toDocument(payment *agg.Payment) (*paymentDocument, error) {
|
||||
|
||||
func fromDocument(doc *paymentDocument) (*agg.Payment, error) {
|
||||
if doc == nil {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil document means no aggregate to hydrate
|
||||
}
|
||||
cloned, err := cloneDocument(doc)
|
||||
if err != nil {
|
||||
@@ -75,7 +75,7 @@ func fromDocument(doc *paymentDocument) (*agg.Payment, error) {
|
||||
|
||||
func cloneDocument(doc *paymentDocument) (*paymentDocument, error) {
|
||||
if doc == nil {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil document means no clone result
|
||||
}
|
||||
data, err := bson.Marshal(doc)
|
||||
if err != nil {
|
||||
|
||||
@@ -2,6 +2,7 @@ package prepo
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/tech/sendico/payments/orchestrator/internal/service/orchestrationv2/agg"
|
||||
@@ -62,7 +63,7 @@ func (s *mongoStore) EnsureIndexes(defs []*indexDefinition) error {
|
||||
opt.SetSparse(true)
|
||||
}
|
||||
if def.TTL != nil {
|
||||
opt.SetExpireAfterSeconds(int32(*def.TTL))
|
||||
opt.SetExpireAfterSeconds(*def.TTL)
|
||||
}
|
||||
if def.PartialFilter != nil {
|
||||
opt.SetPartialFilterExpression(def.PartialFilter.BuildQuery())
|
||||
@@ -174,7 +175,7 @@ func (s *mongoStore) findOne(ctx context.Context, filter bson.D) (*paymentDocume
|
||||
if err == nil {
|
||||
return doc, nil
|
||||
}
|
||||
if err == mongo.ErrNoDocuments {
|
||||
if errors.Is(err, mongo.ErrNoDocuments) {
|
||||
return nil, ErrPaymentNotFound
|
||||
}
|
||||
return nil, err
|
||||
@@ -206,7 +207,9 @@ func (s *mongoStore) list(ctx context.Context, filter bson.D, cursor *listCursor
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cur.Close(ctx)
|
||||
defer func() {
|
||||
_ = cur.Close(ctx)
|
||||
}()
|
||||
|
||||
items := make([]*paymentDocument, 0)
|
||||
for cur.Next(ctx) {
|
||||
|
||||
@@ -587,7 +587,7 @@ func normalizeStepState(state agg.StepState) (agg.StepState, bool) {
|
||||
|
||||
func normalizeCursor(cursor *ListCursor) (*listCursor, error) {
|
||||
if cursor == nil {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil cursor means pagination starts from first page
|
||||
}
|
||||
if cursor.ID.IsZero() {
|
||||
return nil, merrors.InvalidArgument("cursor.id is required")
|
||||
|
||||
@@ -54,7 +54,7 @@ func (s *svc) Map(in MapInput) (out *MapOutput, err error) {
|
||||
|
||||
func mapPayment(src *agg.Payment) (*orchestrationv2.Payment, error) {
|
||||
if src == nil {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil aggregate means no payment to map
|
||||
}
|
||||
|
||||
intentSnapshot, err := mapIntentSnapshot(src.IntentSnapshot)
|
||||
|
||||
@@ -100,8 +100,8 @@ func (s *svc) transitionAggregateState(current, target agg.State) (agg.State, bo
|
||||
if current == target {
|
||||
return current, true, nil
|
||||
}
|
||||
if err := s.state.EnsureAggregateTransition(current, target); err != nil {
|
||||
return current, false, nil
|
||||
if s.state.EnsureAggregateTransition(current, target) != nil {
|
||||
return current, false, nil //nolint:nilerr // invalid transition is treated as a no-op state update
|
||||
}
|
||||
return target, true, nil
|
||||
}
|
||||
|
||||
@@ -381,8 +381,5 @@ func routeContainsCardPayout(snapshot *model.PaymentQuoteSnapshot) bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if model.ParseRail(snapshot.Route.Rail) == discovery.RailCardPayout {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return model.ParseRail(snapshot.Route.Rail) == discovery.RailCardPayout
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ func (s *svc) ListPayments(ctx context.Context, req *orchestrationv2.ListPayment
|
||||
|
||||
func (s *svc) mapPayments(items []*agg.Payment) ([]*orchestrationv2.Payment, error) {
|
||||
if len(items) == 0 {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil slice means no payments in current page
|
||||
}
|
||||
out := make([]*orchestrationv2.Payment, 0, len(items))
|
||||
for i := range items {
|
||||
@@ -160,7 +160,7 @@ func (s *svc) mapPayment(payment *agg.Payment) (*orchestrationv2.Payment, error)
|
||||
return nil, err
|
||||
}
|
||||
if mapped == nil {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil mapped output means mapper produced no payment payload
|
||||
}
|
||||
return mapped.Payment, nil
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ func parsePaymentRef(value string) (string, error) {
|
||||
func parseCursor(value string) (*prepo.ListCursor, error) {
|
||||
raw := strings.TrimSpace(value)
|
||||
if raw == "" {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // empty cursor means pagination starts from first page
|
||||
}
|
||||
data, err := base64.RawURLEncoding.DecodeString(raw)
|
||||
if err != nil {
|
||||
@@ -86,7 +86,7 @@ func formatCursor(cursor *prepo.ListCursor) (string, error) {
|
||||
|
||||
func parseCreated(ts *timestamppb.Timestamp, field string) (*time.Time, error) {
|
||||
if ts == nil {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil timestamp means the filter boundary is not provided
|
||||
}
|
||||
if err := ts.CheckValid(); err != nil {
|
||||
return nil, merrors.InvalidArgument(field + " is invalid")
|
||||
@@ -97,7 +97,7 @@ func parseCreated(ts *timestamppb.Timestamp, field string) (*time.Time, error) {
|
||||
|
||||
func mapStates(states []orchestrationv2.OrchestrationState) ([]agg.State, error) {
|
||||
if len(states) == 0 {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // empty state filter means all states are allowed
|
||||
}
|
||||
out := make([]agg.State, 0, len(states))
|
||||
for i := range states {
|
||||
|
||||
@@ -183,7 +183,6 @@ func TestResolve_InputValidation(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_, err := resolver.Resolve(context.Background(), tt.store, tt.in)
|
||||
if err == nil {
|
||||
|
||||
@@ -290,7 +290,7 @@ func cloneIntentSnapshot(src model.PaymentIntent) (model.PaymentIntent, error) {
|
||||
|
||||
func cloneQuoteSnapshot(src *model.PaymentQuoteSnapshot) (*model.PaymentQuoteSnapshot, error) {
|
||||
if src == nil {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil snapshot means quote data is intentionally absent
|
||||
}
|
||||
dst := &model.PaymentQuoteSnapshot{}
|
||||
if err := bsonClone(src, dst); err != nil {
|
||||
@@ -301,7 +301,7 @@ func cloneQuoteSnapshot(src *model.PaymentQuoteSnapshot) (*model.PaymentQuoteSna
|
||||
|
||||
func cloneStatusSnapshot(src *model.QuoteStatusV2) (*model.QuoteStatusV2, error) {
|
||||
if src == nil {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil snapshot means status data is intentionally absent
|
||||
}
|
||||
dst := &model.QuoteStatusV2{}
|
||||
if err := bsonClone(src, dst); err != nil {
|
||||
|
||||
@@ -200,7 +200,6 @@ func TestValidate_Errors(t *testing.T) {
|
||||
|
||||
v := New()
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ctx, err := v.Validate(tt.req)
|
||||
if err == nil {
|
||||
|
||||
@@ -209,7 +209,6 @@ func TestCompile_ValidationErrors(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_, err := compiler.Compile(tt.in)
|
||||
if !errors.Is(err, merrors.ErrInvalidArg) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package xplan
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/tech/sendico/payments/storage/model"
|
||||
@@ -45,13 +46,5 @@ func railPtr(v model.Rail) *model.Rail {
|
||||
}
|
||||
|
||||
func equalStringSlice(a, b []string) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i := range a {
|
||||
if a[i] != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
return slices.Equal(a, b)
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ func TestGatewayCryptoExecutor_ExecuteCrypto_SubmitsWalletFeeTransferOnSend(t *t
|
||||
}, nil
|
||||
default:
|
||||
t.Fatalf("unexpected transfer submission call %d", len(submitRequests))
|
||||
return nil, nil
|
||||
panic("unreachable")
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -366,7 +366,7 @@ func TestGatewayCryptoExecutor_ExecuteCrypto_ResolvesFeeAddressFromFeeWalletRef(
|
||||
}, nil
|
||||
default:
|
||||
t.Fatalf("unexpected transfer submission call %d", len(submitRequests))
|
||||
return nil, nil
|
||||
panic("unreachable")
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
47
api/payments/quotation/.golangci.yml
Normal file
47
api/payments/quotation/.golangci.yml
Normal file
@@ -0,0 +1,47 @@
|
||||
version: "2"
|
||||
linters:
|
||||
default: none
|
||||
enable:
|
||||
- bodyclose
|
||||
- canonicalheader
|
||||
- copyloopvar
|
||||
- durationcheck
|
||||
- errcheck
|
||||
- errchkjson
|
||||
- errname
|
||||
- errorlint
|
||||
- gosec
|
||||
- govet
|
||||
- ineffassign
|
||||
- nilerr
|
||||
- nilnesserr
|
||||
- nilnil
|
||||
- noctx
|
||||
- rowserrcheck
|
||||
- sqlclosecheck
|
||||
- staticcheck
|
||||
- unconvert
|
||||
- wastedassign
|
||||
disable:
|
||||
- depguard
|
||||
- exhaustruct
|
||||
- gochecknoglobals
|
||||
- gochecknoinits
|
||||
- gomoddirectives
|
||||
- wrapcheck
|
||||
- cyclop
|
||||
- dupl
|
||||
- funlen
|
||||
- gocognit
|
||||
- gocyclo
|
||||
- ireturn
|
||||
- lll
|
||||
- mnd
|
||||
- nestif
|
||||
- nlreturn
|
||||
- noinlineerr
|
||||
- paralleltest
|
||||
- tagliatelle
|
||||
- testpackage
|
||||
- varnamelen
|
||||
- wsl_v5
|
||||
@@ -226,7 +226,7 @@ func (r *discoveryClientResolver) findLedgerEntry() (*discovery.RegistryEntry, b
|
||||
entries := r.registry.List(time.Now(), true)
|
||||
matches := make([]discovery.RegistryEntry, 0)
|
||||
for _, entry := range entries {
|
||||
if !strings.EqualFold(strings.TrimSpace(entry.Service), string(mservice.Ledger)) {
|
||||
if !strings.EqualFold(strings.TrimSpace(entry.Service), mservice.Ledger) {
|
||||
continue
|
||||
}
|
||||
if strings.TrimSpace(entry.InvokeURI) == "" {
|
||||
|
||||
@@ -38,7 +38,7 @@ func SendDirectionForRail(rail model.Rail) SendDirection {
|
||||
}
|
||||
|
||||
func IsGatewayEligible(gw *model.GatewayInstanceDescriptor, rail model.Rail, network, currency string, action model.RailOperation, dir SendDirection, amount decimal.Decimal) error {
|
||||
return model.IsGatewayEligible(gw, rail, network, currency, action, toGatewayDirection(sendDirection(dir)), amount)
|
||||
return model.IsGatewayEligible(gw, rail, network, currency, action, toGatewayDirection(dir), amount)
|
||||
}
|
||||
|
||||
func ParseRailValue(value string) model.Rail {
|
||||
|
||||
@@ -324,7 +324,7 @@ func makeMoney(currency string, value decimal.Decimal) *moneyv1.Money {
|
||||
|
||||
func ensureCurrency(m *moneyv1.Money, targetCurrency string, quote *oraclev1.Quote) (*moneyv1.Money, error) {
|
||||
if m == nil || strings.TrimSpace(targetCurrency) == "" {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil means no amount available for conversion
|
||||
}
|
||||
if strings.EqualFold(m.GetCurrency(), targetCurrency) {
|
||||
return cloneProtoMoney(m), nil
|
||||
@@ -334,12 +334,12 @@ func ensureCurrency(m *moneyv1.Money, targetCurrency string, quote *oraclev1.Quo
|
||||
|
||||
func convertWithQuote(m *moneyv1.Money, quote *oraclev1.Quote, targetCurrency string) (*moneyv1.Money, error) {
|
||||
if m == nil || quote == nil || quote.GetPair() == nil || quote.GetPrice() == nil {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil means conversion cannot be performed with available quote
|
||||
}
|
||||
base := strings.TrimSpace(quote.GetPair().GetBase())
|
||||
qt := strings.TrimSpace(quote.GetPair().GetQuote())
|
||||
if base == "" || qt == "" || strings.TrimSpace(targetCurrency) == "" {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil means conversion cannot be performed with incomplete pair
|
||||
}
|
||||
price, err := decimal.NewFromString(quote.GetPrice().GetValue())
|
||||
if err != nil || price.IsZero() {
|
||||
@@ -355,7 +355,7 @@ func convertWithQuote(m *moneyv1.Money, quote *oraclev1.Quote, targetCurrency st
|
||||
case strings.EqualFold(m.GetCurrency(), qt) && strings.EqualFold(targetCurrency, base):
|
||||
return makeMoney(targetCurrency, value.Div(price)), nil
|
||||
default:
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil means quote pair does not match requested conversion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ func BuildFundingGateFromProfile(
|
||||
requiredAmount *moneyv1.Money,
|
||||
) (*QuoteFundingGate, error) {
|
||||
if profile == nil {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil gate means no funding profile is configured
|
||||
}
|
||||
|
||||
mode := shared.NormalizeFundingMode(profile.Mode)
|
||||
|
||||
@@ -89,7 +89,7 @@ func (r *StaticFundingProfileResolver) ResolveGatewayFundingProfile(
|
||||
req FundingProfileRequest,
|
||||
) (*GatewayFundingProfile, error) {
|
||||
if r == nil {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil resolver means no static funding configuration
|
||||
}
|
||||
|
||||
gatewayKey := r.gatewayKey(req)
|
||||
@@ -206,7 +206,7 @@ func (r *StaticFundingProfileResolver) ResolveGatewayFundingProfile(
|
||||
}
|
||||
|
||||
if isEmptyFundingProfile(profile) {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil profile means funding profile is intentionally omitted
|
||||
}
|
||||
return profile, nil
|
||||
}
|
||||
|
||||
@@ -2,10 +2,11 @@ package graph_path_finder
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/tech/sendico/pkg/discovery"
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/tech/sendico/payments/storage/model"
|
||||
"github.com/tech/sendico/pkg/discovery"
|
||||
"github.com/tech/sendico/pkg/merrors"
|
||||
)
|
||||
|
||||
@@ -142,13 +143,5 @@ func railsToStrings(rails []model.Rail) []string {
|
||||
}
|
||||
|
||||
func equalStrings(got, want []string) bool {
|
||||
if len(got) != len(want) {
|
||||
return false
|
||||
}
|
||||
for i := range got {
|
||||
if got[i] != want[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
return slices.Equal(got, want)
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ func makeMoney(currency string, value decimal.Decimal) *moneyv1.Money {
|
||||
|
||||
func ensureCurrency(m *moneyv1.Money, targetCurrency string, quote *oraclev1.Quote) (*moneyv1.Money, error) {
|
||||
if m == nil || strings.TrimSpace(targetCurrency) == "" {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil means no amount available for conversion
|
||||
}
|
||||
if strings.EqualFold(m.GetCurrency(), targetCurrency) {
|
||||
return cloneProtoMoney(m), nil
|
||||
@@ -250,13 +250,13 @@ func ensureCurrency(m *moneyv1.Money, targetCurrency string, quote *oraclev1.Quo
|
||||
|
||||
func convertWithQuote(m *moneyv1.Money, quote *oraclev1.Quote, targetCurrency string) (*moneyv1.Money, error) {
|
||||
if m == nil || quote == nil || quote.GetPair() == nil || quote.GetPrice() == nil {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil means conversion cannot be performed with available quote
|
||||
}
|
||||
|
||||
base := strings.TrimSpace(quote.GetPair().GetBase())
|
||||
qt := strings.TrimSpace(quote.GetPair().GetQuote())
|
||||
if base == "" || qt == "" || strings.TrimSpace(targetCurrency) == "" {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil means conversion cannot be performed with incomplete pair
|
||||
}
|
||||
|
||||
price, err := decimal.NewFromString(quote.GetPrice().GetValue())
|
||||
@@ -274,7 +274,7 @@ func convertWithQuote(m *moneyv1.Money, quote *oraclev1.Quote, targetCurrency st
|
||||
case strings.EqualFold(m.GetCurrency(), qt) && strings.EqualFold(targetCurrency, base):
|
||||
return makeMoney(targetCurrency, value.Div(price)), nil
|
||||
default:
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil means quote pair does not match requested conversion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,9 +14,9 @@ import (
|
||||
|
||||
func (s *Service) withTimeout(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc) {
|
||||
if d <= 0 {
|
||||
return context.WithCancel(ctx)
|
||||
return context.WithCancel(ctx) //nolint:gosec // cancel func is always invoked by caller
|
||||
}
|
||||
return context.WithTimeout(ctx, d)
|
||||
return context.WithTimeout(ctx, d) //nolint:gosec // cancel func is always invoked by caller
|
||||
}
|
||||
|
||||
func triggerFromKind(kind sharedv1.PaymentKind, requiresFX bool) feesv1.Trigger {
|
||||
|
||||
@@ -989,11 +989,11 @@ type staticManagedWalletResolverForE2E struct {
|
||||
|
||||
func (r staticManagedWalletResolverForE2E) ResolveManagedWalletAsset(_ context.Context, managedWalletRef string) (*paymenttypes.Asset, error) {
|
||||
if len(r.assetsByRef) == 0 {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // test double: empty map means no managed wallet asset
|
||||
}
|
||||
asset, ok := r.assetsByRef[strings.TrimSpace(managedWalletRef)]
|
||||
if !ok || asset == nil {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // test double: unknown wallet means no managed wallet asset
|
||||
}
|
||||
cloned := *asset
|
||||
return &cloned, nil
|
||||
@@ -1009,7 +1009,7 @@ func (r staticManagedWalletResolverForE2E) ResolveManagedWalletNetwork(ctx conte
|
||||
|
||||
func (r staticGatewayRegistryForE2E) List(context.Context) ([]*model.GatewayInstanceDescriptor, error) {
|
||||
if len(r.items) == 0 {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // test double: empty registry means no gateways configured
|
||||
}
|
||||
out := make([]*model.GatewayInstanceDescriptor, 0, len(r.items))
|
||||
for _, item := range r.items {
|
||||
|
||||
@@ -282,11 +282,11 @@ func (f *fakeManagedWalletNetworkResolver) ResolveManagedWalletAsset(_ context.C
|
||||
return nil, f.assetErr
|
||||
}
|
||||
if f.assets == nil {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // test double: nil asset map means no resolved asset
|
||||
}
|
||||
src := f.assets[managedWalletRef]
|
||||
if src == nil {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // test double: missing key means no resolved asset
|
||||
}
|
||||
return &paymenttypes.Asset{
|
||||
Chain: src.GetChain(),
|
||||
|
||||
@@ -421,7 +421,7 @@ func (s *QuoteComputationService) resolveFundingGate(
|
||||
zap.String("rail", string(in.Rail)),
|
||||
)
|
||||
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil gate means no resolver configured
|
||||
}
|
||||
|
||||
s.logger.Debug("Resolving funding gate",
|
||||
@@ -462,7 +462,7 @@ func (s *QuoteComputationService) resolveFundingGate(
|
||||
zap.String("rail", string(in.Rail)),
|
||||
)
|
||||
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil gate means no funding profile for resolved gateway
|
||||
}
|
||||
|
||||
gate, err := gateway_funding_profile.BuildFundingGateFromProfile(profile, in.Amount)
|
||||
|
||||
@@ -432,13 +432,13 @@ func (s *Service) estimateNetworkFee(ctx context.Context, intent *sharedv1.Payme
|
||||
if err != nil {
|
||||
if errors.Is(err, merrors.ErrNoData) {
|
||||
s.logger.Debug("Network fee estimation skipped: gateway unavailable", zap.Error(err))
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil response means fee estimation skipped when gateway is unavailable
|
||||
}
|
||||
s.logger.Warn("Chain gateway resolution failed", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
if client == nil {
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil response means no chain gateway client is available
|
||||
}
|
||||
|
||||
resp, err := client.EstimateTransferFee(ctx, req)
|
||||
@@ -457,7 +457,7 @@ func (s *Service) requestFXQuote(ctx context.Context, orgRef string, req *quoteR
|
||||
if fxRequired {
|
||||
return nil, merrors.Internal("fx_oracle_unavailable")
|
||||
}
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil quote means FX is optional and oracle is unavailable
|
||||
}
|
||||
meta := req.GetMeta()
|
||||
fxIntent := fxIntentForQuote(intent)
|
||||
@@ -465,7 +465,7 @@ func (s *Service) requestFXQuote(ctx context.Context, orgRef string, req *quoteR
|
||||
if fxRequired {
|
||||
return nil, merrors.InvalidArgument("fx intent missing")
|
||||
}
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil quote means FX is not required for this intent
|
||||
}
|
||||
|
||||
ttl := fxIntent.GetTtlMs()
|
||||
@@ -514,7 +514,7 @@ func (s *Service) requestFXQuote(ctx context.Context, orgRef string, req *quoteR
|
||||
if fxRequired {
|
||||
return nil, merrors.Internal("orchestrator: fx quote missing")
|
||||
}
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // nil quote means FX is optional and oracle returned no quote
|
||||
}
|
||||
return quoteToProto(quote), nil
|
||||
}
|
||||
|
||||
@@ -128,10 +128,8 @@ func (h *TransferIntentHydrator) HydrateOne(ctx context.Context, in HydrateOneIn
|
||||
if settlementCurrency == "" {
|
||||
settlementCurrency = settlementCurrencyFromFX(fxIntent)
|
||||
}
|
||||
requiresFX := false
|
||||
if fxIntent != nil && fxIntent.Pair != nil {
|
||||
requiresFX = true
|
||||
} else {
|
||||
requiresFX := fxIntent != nil && fxIntent.Pair != nil
|
||||
if !requiresFX {
|
||||
requiresFX = !strings.EqualFold(amount.Currency, settlementCurrency)
|
||||
}
|
||||
|
||||
|
||||
47
api/payments/storage/.golangci.yml
Normal file
47
api/payments/storage/.golangci.yml
Normal file
@@ -0,0 +1,47 @@
|
||||
version: "2"
|
||||
linters:
|
||||
default: none
|
||||
enable:
|
||||
- bodyclose
|
||||
- canonicalheader
|
||||
- copyloopvar
|
||||
- durationcheck
|
||||
- errcheck
|
||||
- errchkjson
|
||||
- errname
|
||||
- errorlint
|
||||
- gosec
|
||||
- govet
|
||||
- ineffassign
|
||||
- nilerr
|
||||
- nilnesserr
|
||||
- nilnil
|
||||
- noctx
|
||||
- rowserrcheck
|
||||
- sqlclosecheck
|
||||
- staticcheck
|
||||
- unconvert
|
||||
- wastedassign
|
||||
disable:
|
||||
- depguard
|
||||
- exhaustruct
|
||||
- gochecknoglobals
|
||||
- gochecknoinits
|
||||
- gomoddirectives
|
||||
- wrapcheck
|
||||
- cyclop
|
||||
- dupl
|
||||
- funlen
|
||||
- gocognit
|
||||
- gocyclo
|
||||
- ireturn
|
||||
- lll
|
||||
- mnd
|
||||
- nestif
|
||||
- nlreturn
|
||||
- noinlineerr
|
||||
- paralleltest
|
||||
- tagliatelle
|
||||
- testpackage
|
||||
- varnamelen
|
||||
- wsl_v5
|
||||
Reference in New Issue
Block a user