Files
sendico/api/fx/oracle/client/client_test.go
Stephan D 62a6631b9a
All checks were successful
ci/woodpecker/push/db Pipeline was successful
ci/woodpecker/push/nats Pipeline was successful
service backend
2025-11-07 18:35:26 +01:00

117 lines
3.5 KiB
Go

package client
import (
"context"
"testing"
"time"
fxv1 "github.com/tech/sendico/pkg/proto/common/fx/v1"
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
oraclev1 "github.com/tech/sendico/pkg/proto/oracle/v1"
"google.golang.org/grpc"
)
type stubOracle struct {
latestResp *oraclev1.LatestRateResponse
latestErr error
quoteResp *oraclev1.GetQuoteResponse
quoteErr error
lastLatest *oraclev1.LatestRateRequest
lastQuote *oraclev1.GetQuoteRequest
}
func (s *stubOracle) LatestRate(ctx context.Context, in *oraclev1.LatestRateRequest, _ ...grpc.CallOption) (*oraclev1.LatestRateResponse, error) {
s.lastLatest = in
return s.latestResp, s.latestErr
}
func (s *stubOracle) GetQuote(ctx context.Context, in *oraclev1.GetQuoteRequest, _ ...grpc.CallOption) (*oraclev1.GetQuoteResponse, error) {
s.lastQuote = in
return s.quoteResp, s.quoteErr
}
func TestLatestRate(t *testing.T) {
expectedTime := time.Date(2024, 1, 1, 15, 0, 0, 0, time.UTC)
stub := &stubOracle{
latestResp: &oraclev1.LatestRateResponse{
Rate: &oraclev1.RateSnapshot{
Pair: &fxv1.CurrencyPair{Base: "USD", Quote: "EUR"},
Mid: &moneyv1.Decimal{Value: "1.1000"},
Bid: &moneyv1.Decimal{Value: "1.0995"},
Ask: &moneyv1.Decimal{Value: "1.1005"},
SpreadBps: &moneyv1.Decimal{Value: "5"},
Provider: "ECB",
RateRef: "ECB-20240101",
AsofUnixMs: expectedTime.UnixMilli(),
},
},
}
client := NewWithClient(Config{}, stub)
resp, err := client.LatestRate(context.Background(), LatestRateParams{
Meta: RequestMeta{
TenantRef: "tenant",
OrganizationRef: "org",
},
Pair: &fxv1.CurrencyPair{Base: "USD", Quote: "EUR"},
Provider: "ECB",
})
if err != nil {
t.Fatalf("LatestRate returned error: %v", err)
}
if stub.lastLatest.GetProvider() != "ECB" {
t.Fatalf("expected provider to propagate, got %s", stub.lastLatest.GetProvider())
}
if resp.Provider != "ECB" || resp.RateRef != "ECB-20240101" {
t.Fatalf("unexpected response: %+v", resp)
}
if !resp.AsOf.Equal(expectedTime) {
t.Fatalf("expected as-of %s, got %s", expectedTime, resp.AsOf)
}
}
func TestGetQuote(t *testing.T) {
expiresAt := time.Date(2024, 2, 2, 12, 0, 0, 0, time.UTC)
stub := &stubOracle{
quoteResp: &oraclev1.GetQuoteResponse{
Quote: &oraclev1.Quote{
QuoteRef: "quote-123",
Pair: &fxv1.CurrencyPair{Base: "GBP", Quote: "USD"},
Side: fxv1.Side_BUY_BASE_SELL_QUOTE,
Price: &moneyv1.Decimal{Value: "1.2500"},
BaseAmount: &moneyv1.Money{Amount: "100.00", Currency: "GBP"},
QuoteAmount: &moneyv1.Money{Amount: "125.00", Currency: "USD"},
ExpiresAtUnixMs: expiresAt.UnixMilli(),
Provider: "Test",
RateRef: "test-ref",
Firm: true,
},
},
}
client := NewWithClient(Config{}, stub)
resp, err := client.GetQuote(context.Background(), GetQuoteParams{
Pair: &fxv1.CurrencyPair{Base: "GBP", Quote: "USD"},
Side: fxv1.Side_BUY_BASE_SELL_QUOTE,
BaseAmount: &moneyv1.Money{Amount: "100.00", Currency: "GBP"},
Firm: true,
TTL: 2 * time.Second,
})
if err != nil {
t.Fatalf("GetQuote returned error: %v", err)
}
if stub.lastQuote.GetFirm() != true {
t.Fatalf("expected firm flag to propagate")
}
if stub.lastQuote.GetTtlMs() == 0 {
t.Fatalf("expected ttl to be populated")
}
if resp.QuoteRef != "quote-123" || resp.Price != "1.2500" || !resp.ExpiresAt.Equal(expiresAt) {
t.Fatalf("unexpected quote response: %+v", resp)
}
}