package trading212 import ( "context" "encoding/json" "fmt" "time" "github.com/nmoniz/any2anexoj/internal" "github.com/nmoniz/any2anexoj/internal/ofigi" "github.com/shopspring/decimal" ) // recordState is the on-disk representation of a trading212.Record. // Nature is intentionally omitted because it is resolved lazily via the // OpenFIGI client on demand. type recordState struct { Symbol string `json:"symbol"` Timestamp time.Time `json:"timestamp"` Kind internal.Kind `json:"kind"` Quantity decimal.Decimal `json:"quantity"` Price decimal.Decimal `json:"price"` Fees decimal.Decimal `json:"fees"` Taxes decimal.Decimal `json:"taxes"` } // RecordSerializer encodes and decodes trading212.Record values for the // internal persistence layer. On decode it re-wires the lazy natureGetter to // the supplied OpenFIGI client so a restored Record resolves Nature() via a // fresh API call when needed. type RecordSerializer struct { figi *ofigi.Client } // NewRecordSerializer returns a RecordSerializer that uses figi to resolve // Record.Nature() on load. func NewRecordSerializer(figi *ofigi.Client) *RecordSerializer { return &RecordSerializer{figi: figi} } // MarshalRecord encodes the given internal.Record as JSON. It returns an // error if the record is not a trading212.Record (or a *trading212.Record). func (s *RecordSerializer) MarshalRecord(_ context.Context, r internal.Record) ([]byte, error) { var rec Record switch v := r.(type) { case Record: rec = v case *Record: if v == nil { return nil, fmt.Errorf("trading212: cannot marshal nil *trading212.Record") } rec = *v default: return nil, fmt.Errorf("trading212: cannot marshal %T as trading212.Record", r) } state := recordState{ Symbol: rec.symbol, Timestamp: rec.timestamp, Kind: rec.kind, Quantity: rec.quantity, Price: rec.price, Fees: rec.fees, Taxes: rec.taxes, } return json.Marshal(state) } // UnmarshalRecord decodes a JSON-encoded trading212.Record and re-wires its // natureGetter to the serializer's OpenFIGI client. func (s *RecordSerializer) UnmarshalRecord(ctx context.Context, data []byte) (internal.Record, error) { var state recordState if err := json.Unmarshal(data, &state); err != nil { return nil, fmt.Errorf("unmarshal trading212 record: %w", err) } return Record{ symbol: state.Symbol, timestamp: state.Timestamp, kind: state.Kind, quantity: state.Quantity, price: state.Price, fees: state.Fees, taxes: state.Taxes, natureGetter: figiNatureGetter(ctx, s.figi, state.Symbol), }, nil }