Files
sendico/api/payments/quotation/internal/service/quotation/discovery_gateway_registry.go

138 lines
3.5 KiB
Go

package quotation
import (
"context"
"sort"
"strings"
"time"
"github.com/tech/sendico/payments/storage/model"
"github.com/tech/sendico/pkg/discovery"
"github.com/tech/sendico/pkg/mlogger"
)
type discoveryGatewayRegistry struct {
logger mlogger.Logger
registry *discovery.Registry
}
func NewDiscoveryGatewayRegistry(logger mlogger.Logger, registry *discovery.Registry) GatewayRegistry {
if registry == nil {
return nil
}
if logger != nil {
logger = logger.Named("discovery_gateway_registry")
}
return &discoveryGatewayRegistry{
logger: logger,
registry: registry,
}
}
func (r *discoveryGatewayRegistry) List(_ context.Context) ([]*model.GatewayInstanceDescriptor, error) {
if r == nil || r.registry == nil {
return nil, nil
}
entries := r.registry.List(time.Now(), true)
items := make([]*model.GatewayInstanceDescriptor, 0, len(entries))
for _, entry := range entries {
if entry.Rail == "" {
continue
}
rail := railFromDiscovery(entry.Rail)
if rail == model.RailUnspecified {
continue
}
items = append(items, &model.GatewayInstanceDescriptor{
ID: entry.ID,
InstanceID: entry.InstanceID,
Rail: rail,
Network: entry.Network,
InvokeURI: strings.TrimSpace(entry.InvokeURI),
Currencies: normalizeCurrencies(entry.Currencies),
Capabilities: capabilitiesFromOps(entry.Operations),
Limits: limitsFromDiscovery(entry.Limits),
Version: entry.Version,
IsEnabled: entry.Healthy,
})
}
sort.Slice(items, func(i, j int) bool {
return items[i].ID < items[j].ID
})
return items, nil
}
func railFromDiscovery(value string) model.Rail {
switch strings.ToUpper(strings.TrimSpace(value)) {
case string(model.RailCrypto):
return model.RailCrypto
case string(model.RailProviderSettlement):
return model.RailProviderSettlement
case string(model.RailLedger):
return model.RailLedger
case string(model.RailCardPayout):
return model.RailCardPayout
case string(model.RailFiatOnRamp):
return model.RailFiatOnRamp
default:
return model.RailUnspecified
}
}
func capabilitiesFromOps(ops []string) model.RailCapabilities {
var cap model.RailCapabilities
for _, op := range ops {
switch strings.ToLower(strings.TrimSpace(op)) {
case "payin.crypto", "payin.card", "payin.fiat":
cap.CanPayIn = true
case "payout.crypto", "payout.card", "payout.fiat":
cap.CanPayOut = true
case "balance.read":
cap.CanReadBalance = true
case "fee.send":
cap.CanSendFee = true
case "observe.confirm", "observe.confirmation":
cap.RequiresObserveConfirm = true
case "block", "funds.block", "balance.block", "ledger.block":
cap.CanBlock = true
case "release", "funds.release", "balance.release", "ledger.release":
cap.CanRelease = true
}
}
return cap
}
func limitsFromDiscovery(src *discovery.Limits) model.Limits {
if src == nil {
return model.Limits{}
}
limits := model.Limits{
MinAmount: strings.TrimSpace(src.MinAmount),
MaxAmount: strings.TrimSpace(src.MaxAmount),
VolumeLimit: map[string]string{},
VelocityLimit: map[string]int{},
}
for key, value := range src.VolumeLimit {
k := strings.TrimSpace(key)
v := strings.TrimSpace(value)
if k == "" || v == "" {
continue
}
limits.VolumeLimit[k] = v
}
for key, value := range src.VelocityLimit {
k := strings.TrimSpace(key)
if k == "" {
continue
}
limits.VelocityLimit[k] = value
}
if len(limits.VolumeLimit) == 0 {
limits.VolumeLimit = nil
}
if len(limits.VelocityLimit) == 0 {
limits.VelocityLimit = nil
}
return limits
}