Skip to content

Try to decode CBOR-encoded properties in CIP-0068 metadata #59

@euonymos

Description

@euonymos

The current implementation decodes only known fields from the metadata part of the CIP-0068 datums, leaving all additional properties encoded. It drops the availability of this metadata for parties who can't (or don't) parse CBOR for some reason.

At the same time, the standard itself in the sections "Retrieve metadata as 3rd party" (for all 222, 333, and 444) clearly states:

Convert to JSON and encode all string entries to UTF-8 if possible, otherwise leave them in hex.

As a makeshift solution, we are currently using the following decoder. It would be great to have this done on the server's side.

decodeCborValues :: Value -> Identity Value
decodeCborValues (Object obj) = Object <$> traverse decodeCborValues obj
decodeCborValues (Array arr) = Array <$> traverse decodeCborValues arr
decodeCborValues (EncodedData value) = decodeCborValues value
decodeCborValues (NonEncodedData decoded) = pure decoded

pattern EncodedData :: Value -> Value
pattern EncodedData decoded <- (tryDecode -> Just decoded)
pattern NonEncodedData :: Value -> Value
pattern NonEncodedData value <- value
{-# COMPLETE Object, Array, EncodedData, NonEncodedData #-}

tryDecode :: Value -> Maybe Value
tryDecode (String text) = do
  bs <- decodeHex text
  pd <- eitherToMaybe (deserialiseOrFail @Data $ fromStrict bs)
  pdToValue pd
tryDecode _ = Nothing

pdToValue :: Data -> Maybe Value
pdToValue (Map pairs) = Object . Aeson.fromList <$> mapM mapElemToValue pairs
pdToValue (List ds) = Array . Vector.fromList <$> mapM pdToValue ds
pdToValue (I int) = Just $ Number $ fromInteger int
pdToValue (B bs) = eitherToMaybe $ String <$> decodeUtf8' bs
pdToValue (Constr _ _) = Nothing

mapElemToValue :: (Data, Data) -> Maybe (Key, Value)
mapElemToValue (B bs, value) = do
  key <- eitherToMaybe $ decodeUtf8' bs
  value <- pdToValue value
  pure (Aeson.fromText key, value)
mapElemToValue (_, _) = Nothing

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions