68 lines
1.8 KiB
Go
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))
|
|
}
|