package wire import ( "encoding/json" "fmt" decimal "github.com/alpacahq/alpacadecimal" ) // Unwrap returns the inner JSON of an optional {"data": ...} envelope. func Unwrap(raw json.RawMessage) json.RawMessage { if len(raw) == 0 { return raw } var wrap struct { Data json.RawMessage `json:"data"` } if json.Unmarshal(raw, &wrap) == nil && len(wrap.Data) > 0 { return wrap.Data } return raw } // Dec parses a required money/size/price value. func Dec(v any) (decimal.Decimal, error) { switch x := v.(type) { case nil: return decimal.Zero, nil case float64: return decimal.NewFromFloat(x), nil case json.Number: d, err := decimal.NewFromString(string(x)) if err != nil { return decimal.Zero, fmt.Errorf("parse decimal: %v", v) } return d, nil case string: if x == "" { return decimal.Zero, nil } d, err := decimal.NewFromString(x) if err != nil { return decimal.Zero, fmt.Errorf("parse decimal: %v", v) } return d, nil default: return decimal.Zero, fmt.Errorf("parse decimal: %v", v) } } // DecOpt parses an optional money/size/price value. func DecOpt(v any) (*decimal.Decimal, error) { if v == nil { return nil, nil } if s, ok := v.(string); ok && s == "" { return nil, nil } d, err := Dec(v) if err != nil { return nil, err } return &d, nil } // Encode is Decimal.String for Robinhood string wire fields. func Encode(d decimal.Decimal) string { return d.String() }