Files
sendico/api/fx/oracle/internal/service/oracle/math.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

68 lines
1.8 KiB
Go

package oracle
import (
"math/big"
"strings"
"time"
"github.com/tech/sendico/fx/storage/model"
"github.com/tech/sendico/pkg/decimal"
"github.com/tech/sendico/pkg/merrors"
fxv1 "github.com/tech/sendico/pkg/proto/common/fx/v1"
)
// Convenience aliases to pkg/decimal for backward compatibility
var (
ratFromString = decimal.RatFromString
mulRat = decimal.MulRat
divRat = decimal.DivRat
formatRat = decimal.FormatRat
)
// roundRatToScale wraps pkg/decimal.RoundRatToScale with model RoundingMode conversion
func roundRatToScale(value *big.Rat, scale uint32, mode model.RoundingMode) (*big.Rat, error) {
return decimal.RoundRatToScale(value, scale, convertRoundingMode(mode))
}
// convertRoundingMode converts fx/storage model.RoundingMode to pkg/decimal.RoundingMode
func convertRoundingMode(mode model.RoundingMode) decimal.RoundingMode {
switch mode {
case model.RoundingModeHalfEven:
return decimal.RoundingModeHalfEven
case model.RoundingModeHalfUp:
return decimal.RoundingModeHalfUp
case model.RoundingModeDown:
return decimal.RoundingModeDown
case model.RoundingModeUnspecified:
return decimal.RoundingModeUnspecified
default:
return decimal.RoundingModeHalfEven
}
}
func priceFromRate(rate *model.RateSnapshot, side fxv1.Side) (*big.Rat, error) {
var priceStr string
switch side {
case fxv1.Side_BUY_BASE_SELL_QUOTE:
priceStr = rate.Ask
case fxv1.Side_SELL_BASE_BUY_QUOTE:
priceStr = rate.Bid
default:
priceStr = ""
}
if strings.TrimSpace(priceStr) == "" {
priceStr = rate.Mid
}
if strings.TrimSpace(priceStr) == "" {
return nil, merrors.InvalidArgument("oracle: rate snapshot missing price")
}
return ratFromString(priceStr)
}
func timeFromUnixMilli(ms int64) time.Time {
return time.Unix(0, ms*int64(time.Millisecond))
}