Fixes + stable gateway ids

This commit is contained in:
Stephan D
2026-02-18 20:38:08 +01:00
parent 4dc182bfa2
commit 770c7b9da9
119 changed files with 3000 additions and 734 deletions

View File

@@ -0,0 +1,27 @@
package discovery
import "strings"
// StableGatewayID composes a stable discovery entry ID from a base prefix and key.
func StableGatewayID(prefix string, key string) string {
cleanPrefix := strings.ToLower(strings.TrimSpace(prefix))
cleanKey := strings.ToLower(strings.TrimSpace(key))
if cleanKey == "" {
cleanKey = "unknown"
}
if cleanPrefix == "" {
return cleanKey
}
if strings.HasSuffix(cleanPrefix, "_") {
return cleanPrefix + cleanKey
}
return cleanPrefix + "_" + cleanKey
}
func StableCryptoRailGatewayID(network string) string {
return StableGatewayID("crypto_rail_gateway", network)
}
func StablePaymentGatewayID(rail string) string {
return StableGatewayID("payment_gateway", rail)
}

View File

@@ -0,0 +1,44 @@
package discovery
import "testing"
func TestStableGatewayID(t *testing.T) {
cases := []struct {
name string
prefix string
key string
want string
}{
{name: "prefix and key", prefix: "crypto_rail_gateway", key: " TRON ", want: "crypto_rail_gateway_tron"},
{name: "prefix trailing underscore", prefix: "payment_gateway_", key: " PROVIDER_SETTLEMENT ", want: "payment_gateway_provider_settlement"},
{name: "missing key", prefix: "payment_gateway", key: " ", want: "payment_gateway_unknown"},
{name: "missing prefix", prefix: " ", key: "TRON", want: "tron"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got := StableGatewayID(tc.prefix, tc.key)
if got != tc.want {
t.Fatalf("unexpected stable gateway id: got=%q want=%q", got, tc.want)
}
})
}
}
func TestStableCryptoRailGatewayID(t *testing.T) {
if got, want := StableCryptoRailGatewayID(" TRON "), "crypto_rail_gateway_tron"; got != want {
t.Fatalf("unexpected stable id: got=%q want=%q", got, want)
}
if got, want := StableCryptoRailGatewayID(""), "crypto_rail_gateway_unknown"; got != want {
t.Fatalf("unexpected stable id for empty network: got=%q want=%q", got, want)
}
}
func TestStablePaymentGatewayID(t *testing.T) {
if got, want := StablePaymentGatewayID(" PROVIDER_SETTLEMENT "), "payment_gateway_provider_settlement"; got != want {
t.Fatalf("unexpected stable id: got=%q want=%q", got, want)
}
if got, want := StablePaymentGatewayID(""), "payment_gateway_unknown"; got != want {
t.Fatalf("unexpected stable id for empty rail: got=%q want=%q", got, want)
}
}

View File

@@ -16,11 +16,11 @@ type ChainAsset struct {
}
type ChainAssetDescription struct {
storable.Storable `bson:",inline" json:",inline"`
Describable `bson:",inline" json:",inline"`
Asset ChainAsset `bson:"asset" json:"asset"`
storable.Base `bson:",inline" json:",inline"`
Describable `bson:",inline" json:",inline"`
Asset ChainAsset `bson:"asset" json:"asset"`
}
func Collection(*ChainAssetDescription) mservice.Type {
func (*ChainAssetDescription) Collection() string {
return mservice.ChainAssets
}

View File

@@ -0,0 +1,21 @@
package model
import (
"testing"
"github.com/tech/sendico/pkg/db/storable"
"github.com/tech/sendico/pkg/mservice"
)
func TestChainAssetDescriptionImplementsStorable(t *testing.T) {
var _ storable.Storable = (*ChainAssetDescription)(nil)
}
func TestChainAssetDescriptionCollection(t *testing.T) {
var desc ChainAssetDescription
want := string(mservice.ChainAssets)
if got := desc.Collection(); got != want {
t.Fatalf("Collection() = %q, want %q", got, want)
}
}

View File

@@ -28,18 +28,22 @@ type QuoteRouteHop struct {
Role QuoteRouteHopRole `bson:"role,omitempty" json:"role,omitempty"`
}
type QuoteRouteSettlement struct {
Asset *Asset `bson:"asset,omitempty" json:"asset,omitempty"`
Model string `bson:"model,omitempty" json:"model,omitempty"`
}
// QuoteRouteSpecification is an abstract route selected during quotation.
// It intentionally omits execution steps/operations.
type QuoteRouteSpecification struct {
Rail string `bson:"rail,omitempty" json:"rail,omitempty"`
Provider string `bson:"provider,omitempty" json:"provider,omitempty"`
PayoutMethod string `bson:"payoutMethod,omitempty" json:"payoutMethod,omitempty"`
SettlementAsset string `bson:"settlementAsset,omitempty" json:"settlementAsset,omitempty"`
SettlementModel string `bson:"settlementModel,omitempty" json:"settlementModel,omitempty"`
Network string `bson:"network,omitempty" json:"network,omitempty"`
RouteRef string `bson:"routeRef,omitempty" json:"routeRef,omitempty"`
PricingProfileRef string `bson:"pricingProfileRef,omitempty" json:"pricingProfileRef,omitempty"`
Hops []*QuoteRouteHop `bson:"hops,omitempty" json:"hops,omitempty"`
Rail string `bson:"rail,omitempty" json:"rail,omitempty"`
Provider string `bson:"provider,omitempty" json:"provider,omitempty"`
PayoutMethod string `bson:"payoutMethod,omitempty" json:"payoutMethod,omitempty"`
Settlement *QuoteRouteSettlement `bson:"settlement,omitempty" json:"settlement,omitempty"`
Network string `bson:"network,omitempty" json:"network,omitempty"`
RouteRef string `bson:"routeRef,omitempty" json:"routeRef,omitempty"`
PricingProfileRef string `bson:"pricingProfileRef,omitempty" json:"pricingProfileRef,omitempty"`
Hops []*QuoteRouteHop `bson:"hops,omitempty" json:"hops,omitempty"`
}
// QuoteExecutionConditions stores quotation-time assumptions and constraints.

Binary file not shown.