package model import ( "encoding/json" "fmt" "strings" "git.sendico.io/tech/sxchnge/bff/pkg/merrors" "go.mongodb.org/mongo-driver/v2/bson" ) type CryptoAddressPaymentData struct { Currency Currency `bson:"currency" json:"currency"` Address string `bson:"address" json:"address"` Network string `bson:"network" json:"network"` DestinationTag *string `bson:"destinationTag,omitempty" json:"destinationTag,omitempty"` } type cryptoAddressAssetJSON struct { Chain string `json:"chain,omitempty"` TokenSymbol string `json:"token_symbol,omitempty"` ContractAddress string `json:"contract_address,omitempty"` } func (d CryptoAddressPaymentData) MarshalJSON() ([]byte, error) { var payload struct { Asset *cryptoAddressAssetJSON `json:"asset,omitempty"` Address string `json:"address"` Memo *string `json:"memo,omitempty"` } payload.Address = strings.TrimSpace(d.Address) if strings.TrimSpace(d.Network) != "" || strings.TrimSpace(string(d.Currency)) != "" { payload.Asset = &cryptoAddressAssetJSON{ Chain: strings.TrimSpace(d.Network), TokenSymbol: strings.TrimSpace(string(d.Currency)), } } if memo := strings.TrimSpace(strPtr(d.DestinationTag)); memo != "" { payload.Memo = &memo } return json.Marshal(payload) } func (d *CryptoAddressPaymentData) UnmarshalJSON(data []byte) error { var raw struct { Asset *cryptoAddressAssetJSON `json:"asset"` Address string `json:"address"` Memo string `json:"memo"` Currency string `json:"currency"` Network string `json:"network"` DestinationTag *string `json:"destinationTag"` } if err := json.Unmarshal(data, &raw); err != nil { return err } currency := strings.TrimSpace(raw.Currency) network := strings.TrimSpace(raw.Network) if raw.Asset != nil { if assetCurrency := strings.TrimSpace(raw.Asset.TokenSymbol); assetCurrency != "" { currency = assetCurrency } if assetNetwork := strings.TrimSpace(raw.Asset.Chain); assetNetwork != "" { network = assetNetwork } } d.Currency = Currency(strings.ToUpper(currency)) d.Address = strings.TrimSpace(raw.Address) d.Network = strings.ToUpper(network) d.DestinationTag = clonePaymentDataStringPtr(raw.Memo) if d.DestinationTag == nil && raw.DestinationTag != nil { d.DestinationTag = clonePaymentDataStringPtr(*raw.DestinationTag) } return nil } func (d *CryptoAddressPaymentData) UnmarshalBSON(data []byte) error { var raw map[string]any if err := bson.Unmarshal(data, &raw); err != nil { return err } currency := firstPaymentDataString(raw, "currency") network := firstPaymentDataString(raw, "network") if asset := paymentDataDocument(raw["asset"]); asset != nil { if assetCurrency := firstPaymentDataString(asset, "token_symbol", "tokenSymbol"); assetCurrency != "" { currency = assetCurrency } if assetNetwork := firstPaymentDataString(asset, "chain"); assetNetwork != "" { network = assetNetwork } } d.Currency = Currency(strings.ToUpper(strings.TrimSpace(currency))) d.Address = firstPaymentDataString(raw, "address") d.Network = strings.ToUpper(strings.TrimSpace(network)) d.DestinationTag = clonePaymentDataStringPtr(firstPaymentDataString(raw, "destinationTag", "destination_tag", "memo")) return nil } func (m *PaymentMethod) AsCryptoAddress() (*CryptoAddressPaymentData, error) { if m.Type != PaymentTypeCryptoAddress { return nil, merrors.InvalidArgument(fmt.Sprintf("payment method type is %s, not cryptoAddress", m.Type), "type") } var d CryptoAddressPaymentData if err := bson.Unmarshal(m.Data, &d); err != nil { return nil, err } return &d, nil } func clonePaymentDataStringPtr(value string) *string { out := strings.TrimSpace(value) if out == "" { return nil } return &out } func strPtr(value *string) string { if value == nil { return "" } return *value }