Fixed billing fees unreachable error propagation. Added USDT ledger creation. Fixed ledger boundaries operation types
This commit is contained in:
@@ -52,7 +52,7 @@ func (i *Imp) startDiscoveryAnnouncer(cfg *config, producer msg.Producer) {
|
||||
|
||||
announce := discovery.Announcement{
|
||||
Service: "PAYMENTS_QUOTATION",
|
||||
Operations: []string{"payment.quote", "payment.multiquote"},
|
||||
Operations: []string{discovery.OperationPaymentQuote, discovery.OperationPaymentMultiQuote},
|
||||
InvokeURI: invokeURI,
|
||||
Version: appversion.Create().Short(),
|
||||
}
|
||||
|
||||
@@ -197,18 +197,6 @@ func (r *managedWalletNetworkResolver) listDiscoveredGatewayCandidates(ctx conte
|
||||
return candidates, nil
|
||||
}
|
||||
|
||||
func managedWalletNetworkFromResponse(resp *chainv1.GetManagedWalletResponse) (string, error) {
|
||||
asset, err := managedWalletAssetFromResponse(resp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
network := strings.ToUpper(strings.TrimSpace(asset.GetChain()))
|
||||
if network == "" || network == "UNSPECIFIED" {
|
||||
return "", merrors.NoData("managed wallet network is missing")
|
||||
}
|
||||
return network, nil
|
||||
}
|
||||
|
||||
func managedWalletAssetFromResponse(resp *chainv1.GetManagedWalletResponse) (*paymenttypes.Asset, error) {
|
||||
wallet := resp.GetWallet()
|
||||
if wallet == nil || wallet.GetAsset() == nil {
|
||||
|
||||
@@ -8,7 +8,3 @@ import (
|
||||
func railFromEndpoint(endpoint model.PaymentEndpoint, attrs map[string]string, isSource bool) (model.Rail, string, error) {
|
||||
return plan.RailFromEndpoint(endpoint, attrs, isSource)
|
||||
}
|
||||
|
||||
func resolveRouteNetwork(attrs map[string]string, sourceNetwork, destNetwork string) (string, error) {
|
||||
return plan.ResolveRouteNetwork(attrs, sourceNetwork, destNetwork)
|
||||
}
|
||||
|
||||
@@ -152,7 +152,8 @@ func (s *Service) buildPaymentQuote(ctx context.Context, orgRef string, req *quo
|
||||
|
||||
func (s *Service) quoteFees(ctx context.Context, orgRef string, req *quoteRequest, baseAmount *moneyv1.Money) (*feesv1.PrecomputeFeesResponse, error) {
|
||||
if !s.deps.fees.available() {
|
||||
return &feesv1.PrecomputeFeesResponse{}, nil
|
||||
s.logger.Warn("Fees precompute failed: fee engine unavailable")
|
||||
return nil, merrors.Internal("fees_precompute_failed")
|
||||
}
|
||||
intent := req.GetIntent()
|
||||
amount := cloneProtoMoney(baseAmount)
|
||||
@@ -188,7 +189,8 @@ func (s *Service) quoteFees(ctx context.Context, orgRef string, req *quoteReques
|
||||
|
||||
func (s *Service) quoteConversionFees(ctx context.Context, orgRef string, req *quoteRequest, baseAmount *moneyv1.Money) (*feesv1.PrecomputeFeesResponse, error) {
|
||||
if !s.deps.fees.available() {
|
||||
return &feesv1.PrecomputeFeesResponse{}, nil
|
||||
s.logger.Warn("Conversion fee precompute failed: fee engine unavailable")
|
||||
return nil, merrors.Internal("fees_precompute_failed")
|
||||
}
|
||||
intent := req.GetIntent()
|
||||
amount := cloneProtoMoney(baseAmount)
|
||||
|
||||
@@ -2,6 +2,7 @@ package quotation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -152,9 +153,89 @@ func TestBuildPaymentQuote_DoesNotRequestConversionFeesForManagedWalletToLedger(
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildPaymentQuote_ReturnsErrorWhenFeeEngineUnavailable(t *testing.T) {
|
||||
svc := NewService(zap.NewNop(), nil)
|
||||
req := "eRequest{
|
||||
Meta: &sharedv1.RequestMeta{OrganizationRef: "org_1"},
|
||||
IdempotencyKey: "idem_1",
|
||||
Intent: testManagedWalletToCardIntent(),
|
||||
}
|
||||
|
||||
_, _, err := svc.buildPaymentQuote(context.Background(), "org_1", req)
|
||||
if err == nil {
|
||||
t.Fatalf("expected error")
|
||||
}
|
||||
if !errors.Is(err, merrors.ErrInternal) {
|
||||
t.Fatalf("expected internal error, got: %v", err)
|
||||
}
|
||||
if !strings.Contains(err.Error(), "fees_precompute_failed") {
|
||||
t.Fatalf("expected fees_precompute_failed error, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildPaymentQuote_ReturnsErrorWhenBaseFeePrecomputeFails(t *testing.T) {
|
||||
feeClient := &stubFeeEngineClient{
|
||||
precomputeErrByOrigin: map[string]error{
|
||||
"payments.orchestrator.quote": merrors.Internal("billing_fees_unreachable"),
|
||||
},
|
||||
}
|
||||
|
||||
svc := NewService(zap.NewNop(), nil, WithFeeEngine(feeClient, 0))
|
||||
req := "eRequest{
|
||||
Meta: &sharedv1.RequestMeta{OrganizationRef: "org_1"},
|
||||
IdempotencyKey: "idem_1",
|
||||
Intent: testManagedWalletToLedgerIntent(),
|
||||
}
|
||||
|
||||
_, _, err := svc.buildPaymentQuote(context.Background(), "org_1", req)
|
||||
if err == nil {
|
||||
t.Fatalf("expected error")
|
||||
}
|
||||
if !errors.Is(err, merrors.ErrInternal) {
|
||||
t.Fatalf("expected internal error, got: %v", err)
|
||||
}
|
||||
if !strings.Contains(err.Error(), "fees_precompute_failed") {
|
||||
t.Fatalf("expected fees_precompute_failed error, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildPaymentQuote_ReturnsErrorWhenConversionFeePrecomputeFails(t *testing.T) {
|
||||
feeClient := &stubFeeEngineClient{
|
||||
precomputeByOrigin: map[string]*feesv1.PrecomputeFeesResponse{
|
||||
"payments.orchestrator.quote": {
|
||||
Lines: []*feesv1.DerivedPostingLine{
|
||||
testFeeLine("1.00", "USDT"),
|
||||
},
|
||||
},
|
||||
},
|
||||
precomputeErrByOrigin: map[string]error{
|
||||
"payments.orchestrator.conversion_quote": merrors.Internal("billing_fees_unreachable"),
|
||||
},
|
||||
}
|
||||
|
||||
svc := NewService(zap.NewNop(), nil, WithFeeEngine(feeClient, 0))
|
||||
req := "eRequest{
|
||||
Meta: &sharedv1.RequestMeta{OrganizationRef: "org_1"},
|
||||
IdempotencyKey: "idem_1",
|
||||
Intent: testManagedWalletToCardIntent(),
|
||||
}
|
||||
|
||||
_, _, err := svc.buildPaymentQuote(context.Background(), "org_1", req)
|
||||
if err == nil {
|
||||
t.Fatalf("expected error")
|
||||
}
|
||||
if !errors.Is(err, merrors.ErrInternal) {
|
||||
t.Fatalf("expected internal error, got: %v", err)
|
||||
}
|
||||
if !strings.Contains(err.Error(), "fees_precompute_failed") {
|
||||
t.Fatalf("expected fees_precompute_failed error, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
type stubFeeEngineClient struct {
|
||||
precomputeByOrigin map[string]*feesv1.PrecomputeFeesResponse
|
||||
precomputeReqs []*feesv1.PrecomputeFeesRequest
|
||||
precomputeByOrigin map[string]*feesv1.PrecomputeFeesResponse
|
||||
precomputeErrByOrigin map[string]error
|
||||
precomputeReqs []*feesv1.PrecomputeFeesRequest
|
||||
}
|
||||
|
||||
func (s *stubFeeEngineClient) QuoteFees(context.Context, *feesv1.QuoteFeesRequest, ...grpc.CallOption) (*feesv1.QuoteFeesResponse, error) {
|
||||
@@ -177,6 +258,9 @@ func (s *stubFeeEngineClient) PrecomputeFees(_ context.Context, in *feesv1.Preco
|
||||
}
|
||||
|
||||
originType := strings.TrimSpace(in.GetIntent().GetOriginType())
|
||||
if err := s.precomputeErrByOrigin[originType]; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, ok := s.precomputeByOrigin[originType]
|
||||
if !ok || resp == nil {
|
||||
return &feesv1.PrecomputeFeesResponse{}, nil
|
||||
|
||||
Reference in New Issue
Block a user