From 739408fb39c7d7029d6845049ba7a2244566bc8c Mon Sep 17 00:00:00 2001 From: Jamie Bertram Date: Mon, 27 Nov 2023 09:44:18 -0500 Subject: [PATCH] Add support for additional properties on token file metadata --- marlowe-runtime-web/.golden/OpenApi/golden | 3 + .../Marlowe/Runtime/Web/Server/DTO.hs | 5 +- .../src/Language/Marlowe/Runtime/Web/Types.hs | 12 +++- marlowe-runtime-web/test/Spec.hs | 20 ++++++- .../.golden/Job MarloweTxCommand/golden | 60 ++++++++++++------- .../Marlowe/Runtime/Transaction/Gen.hs | 1 + .../Marlowe/Runtime/Transaction/ApiSpec.hs | 3 +- .../Marlowe/Runtime/Transaction/Api.hs | 12 +++- 8 files changed, 89 insertions(+), 27 deletions(-) diff --git a/marlowe-runtime-web/.golden/OpenApi/golden b/marlowe-runtime-web/.golden/OpenApi/golden index 3139c38bfe..28d6fc8d64 100644 --- a/marlowe-runtime-web/.golden/OpenApi/golden +++ b/marlowe-runtime-web/.golden/OpenApi/golden @@ -2418,6 +2418,9 @@ "type": "object" }, "TokenMetadataFile": { + "additionalProperties": { + "$ref": "#/components/schemas/Metadata" + }, "properties": { "mediaType": { "type": "string" diff --git a/marlowe-runtime-web/server/Language/Marlowe/Runtime/Web/Server/DTO.hs b/marlowe-runtime-web/server/Language/Marlowe/Runtime/Web/Server/DTO.hs index b43f73a6d5..585cdfe7c9 100644 --- a/marlowe-runtime-web/server/Language/Marlowe/Runtime/Web/Server/DTO.hs +++ b/marlowe-runtime-web/server/Language/Marlowe/Runtime/Web/Server/DTO.hs @@ -855,7 +855,10 @@ instance HasDTO Tx.NFTMetadataFile where instance FromDTO Tx.NFTMetadataFile where fromDTO Web.TokenMetadataFile{..} = - Tx.NFTMetadataFile name <$> fromDTO mediaType <*> pure src + Tx.NFTMetadataFile name + <$> fromDTO mediaType + <*> pure src + <*> traverse fromDTO (Map.mapKeys Key.toText $ KeyMap.toMap $ Web.Metadata <$> additionalProps) instance HasDTO Query.Order where type DTO Query.Order = Pagination.RangeOrder diff --git a/marlowe-runtime-web/src/Language/Marlowe/Runtime/Web/Types.hs b/marlowe-runtime-web/src/Language/Marlowe/Runtime/Web/Types.hs index 38e310f190..41aaaa9d15 100644 --- a/marlowe-runtime-web/src/Language/Marlowe/Runtime/Web/Types.hs +++ b/marlowe-runtime-web/src/Language/Marlowe/Runtime/Web/Types.hs @@ -1076,28 +1076,37 @@ data TokenMetadataFile = TokenMetadataFile { name :: Text , src :: URI , mediaType :: Text + , additionalProps :: Aeson.Object } deriving (Show, Eq, Ord, Generic) instance FromJSON TokenMetadataFile where parseJSON = withObject "TokenMetadataFile" \obj -> do srcJSON <- obj .: "src" + let additionalProps = + AMap.delete "name" + . AMap.delete "mediaType" + . AMap.delete "src" + $ obj TokenMetadataFile <$> obj .: "name" <*> uriFromJSON srcJSON <*> obj .: "mediaType" + <*> pure additionalProps instance ToJSON TokenMetadataFile where toJSON TokenMetadataFile{..} = - object + object $ [ ("name", toJSON name) , ("src", uriToJSON src) , ("mediaType", toJSON mediaType) ] + <> AMap.toList additionalProps instance ToSchema TokenMetadataFile where declareNamedSchema _ = do stringSchema <- declareSchemaRef (Proxy @Text) + metadataSchema <- declareSchemaRef (Proxy @Metadata) pure $ NamedSchema (Just "TokenMetadataFile") $ mempty @@ -1108,6 +1117,7 @@ instance ToSchema TokenMetadataFile where , ("src", stringSchema) , ("mediaType", stringSchema) ] + & additionalProperties ?~ AdditionalPropertiesSchema metadataSchema uriFromJSON :: Value -> Parser URI uriFromJSON = withText "URI" $ maybe (parseFail "invalid URI") pure . parseURI . T.unpack diff --git a/marlowe-runtime-web/test/Spec.hs b/marlowe-runtime-web/test/Spec.hs index bc471bdd2f..6f495d59d9 100644 --- a/marlowe-runtime-web/test/Spec.hs +++ b/marlowe-runtime-web/test/Spec.hs @@ -46,7 +46,7 @@ import Spec.Marlowe.Semantics.Arbitrary () import Spec.Marlowe.Semantics.Next.Arbitrary () import Test.Hspec (Spec, describe, hspec, it, shouldBe) import Test.Hspec.Golden (defaultGolden) -import Test.QuickCheck (Arbitrary (..), Gen, elements, genericShrink, listOf, oneof, resize, suchThat) +import Test.QuickCheck (Arbitrary (..), Gen, chooseInt, elements, genericShrink, listOf, oneof, resize, sized, suchThat) import Test.QuickCheck.Instances () import Text.Regex.Posix ((=~)) @@ -578,12 +578,26 @@ instance Arbitrary Web.TokenMetadata where <*> arbitrary <*> arbitrary <*> arbitrary - <*> arbitrary + <*> oneof + [ pure Nothing + , Just <$> sized \size -> do + len <- chooseInt (0, size) + case len of + 0 -> pure [] + _ -> do + let itemSize = size `div` len + resize itemSize $ replicateM len arbitrary + ] <*> arbitrary shrink = genericShrink instance Arbitrary Web.TokenMetadataFile where - arbitrary = Web.TokenMetadataFile <$> arbitrary <*> arbitrary <*> arbitrary + arbitrary = + Web.TokenMetadataFile + <$> arbitrary + <*> arbitrary + <*> arbitrary + <*> arbitrary shrink = genericShrink instance Arbitrary Web.Address where diff --git a/marlowe-runtime/.golden/Job MarloweTxCommand/golden b/marlowe-runtime/.golden/Job MarloweTxCommand/golden index f7f188a79f..1b8530d77b 100644 --- a/marlowe-runtime/.golden/Job MarloweTxCommand/golden +++ b/marlowe-runtime/.golden/Job MarloweTxCommand/golden @@ -944,26 +944,46 @@ Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", ex Binary: 010100000001000000000000000000000000000000000000000000000000000002000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Just "a", files = [], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000016100000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 -Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = //a}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) -Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e000000000000000001000000000000000000000000000000000000000000000001610000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 -Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = //a}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) -Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e000000000000000001000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 -Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = //a}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) -Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e000000000000000001000000000000000161000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 -Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = //}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) -Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e0000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 -Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = a}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) -Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e000000000000000000000000000000000000000000000000000000000000000001610000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 -Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = a}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) -Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 -Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = a}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) -Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e000000000000000000000000000000000161000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 -Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = a}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) -Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e000000000000000161000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 -Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = }], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) -Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 -Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "a", mediaType = text/plain, src = }], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) -Binary: 0101000000010000000000000000000000000000000000000000000000000000020000000000000001000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000161000000000000000a746578742f706c61696e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 +Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = , additionalProperties = fromList [("",MetadataBytes "")]}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) +Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000300000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 +Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = , additionalProperties = fromList [("",MetadataBytes "a")]}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) +Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e00000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000030000000000000001610000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 +Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = , additionalProperties = fromList [("",MetadataList [MetadataMap []])]}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) +Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000010000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 +Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = , additionalProperties = fromList [("",MetadataList [])]}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) +Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 +Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = , additionalProperties = fromList [("",MetadataMap [(MetadataMap [],MetadataMap [])])]}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) +Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 +Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = , additionalProperties = fromList [("",MetadataMap [])]}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) +Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 +Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = , additionalProperties = fromList [("",MetadataNumber 1)]}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) +Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000200000000010000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 +Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = , additionalProperties = fromList [("",MetadataText "")]}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) +Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000400000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 +Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = , additionalProperties = fromList [("",MetadataText "a")]}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) +Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e00000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000040000000000000001610000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 +Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = , additionalProperties = fromList [("a",MetadataMap [])]}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) +Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e00000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001610000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 +Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = , additionalProperties = fromList []}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) +Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 +Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = //, additionalProperties = fromList []}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) +Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e00000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 +Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = //a, additionalProperties = fromList []}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) +Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e0000000000000000010000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 +Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = //a, additionalProperties = fromList []}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) +Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e0000000000000000010000000000000000000000000000000161000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 +Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = //a, additionalProperties = fromList []}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) +Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e0000000000000000010000000000000001610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 +Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = a, additionalProperties = fromList []}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) +Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e0000000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 +Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = a, additionalProperties = fromList []}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) +Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e0000000000000000000000000000000000000000000000000161000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 +Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = a, additionalProperties = fromList []}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) +Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e0000000000000000000000000000000001610000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 +Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "", mediaType = text/plain, src = a, additionalProperties = fromList []}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) +Binary: 01010000000100000000000000000000000000000000000000000000000000000200000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000a746578742f706c61696e0000000000000001610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 +Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [NFTMetadataFile {name = "a", mediaType = text/plain, src = , additionalProperties = fromList []}], additionalProperties = fromList []}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) +Binary: 0101000000010000000000000000000000000000000000000000000000000000020000000000000001000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000161000000000000000a746578742f706c61696e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [], additionalProperties = fromList [("",MetadataBytes "")]}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) Binary: 010100000001000000000000000000000000000000000000000000000000000002000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000030000000000000000000000000000000100000000000000000000000000000000010000000000000000000000 Show: MsgExec (Create Nothing MarloweV1 (WalletAddresses {changeAddress = "", extraAddresses = fromList [], collateralUtxos = fromList []}) Nothing (UnsafeRoleTokensMint (Mint {unMint = fromList (("",MintRole {roleMetadata = Just (RoleTokenMetadata {name = "", image = , mediaType = Nothing, description = Nothing, files = [], additionalProperties = fromList [("",MetadataBytes "a")]}), roleTokenRecipients = fromList ((ToAddress "",Quantity {unQuantity = 1}) :| [])}) :| [])})) (MarloweTransactionMetadata {marloweMetadata = Nothing, transactionMetadata = TransactionMetadata {unTransactionMetadata = fromList []}}) Nothing (Left Close)) diff --git a/marlowe-runtime/gen/Language/Marlowe/Runtime/Transaction/Gen.hs b/marlowe-runtime/gen/Language/Marlowe/Runtime/Transaction/Gen.hs index 8e258a1e30..8dc37a5229 100644 --- a/marlowe-runtime/gen/Language/Marlowe/Runtime/Transaction/Gen.hs +++ b/marlowe-runtime/gen/Language/Marlowe/Runtime/Transaction/Gen.hs @@ -90,6 +90,7 @@ instance Arbitrary NFTMetadataFile where <$> arbitrary <*> arbitrary <*> arbitrary + <*> arbitrary shrink = genericShrink instance Arbitrary RoleTokenMetadata where diff --git a/marlowe-runtime/test/Language/Marlowe/Runtime/Transaction/ApiSpec.hs b/marlowe-runtime/test/Language/Marlowe/Runtime/Transaction/ApiSpec.hs index 797bccc769..83be62bce1 100644 --- a/marlowe-runtime/test/Language/Marlowe/Runtime/Transaction/ApiSpec.hs +++ b/marlowe-runtime/test/Language/Marlowe/Runtime/Transaction/ApiSpec.hs @@ -147,7 +147,8 @@ cip25MetadataFileDetailsJSONRelationGen = do name <- Gen.oneof [pure "", fromString <$> Gen.listOf1 Gen.arbitrary] (mediaType, mediaTypeJSON) <- mediaTypeJSONRelationGen (src, srcJSON) <- uriJSONRelationGen - let json = + let additionalProperties = mempty -- Here we don't test roundtrip for additional properties, which is not in invertible in general. + json = Aeson.Object [ ("name", Aeson.String name) , ("mediaType", mediaTypeJSON) diff --git a/marlowe-runtime/tx-api/Language/Marlowe/Runtime/Transaction/Api.hs b/marlowe-runtime/tx-api/Language/Marlowe/Runtime/Transaction/Api.hs index ce3bafd3aa..9898f6657b 100644 --- a/marlowe-runtime/tx-api/Language/Marlowe/Runtime/Transaction/Api.hs +++ b/marlowe-runtime/tx-api/Language/Marlowe/Runtime/Transaction/Api.hs @@ -171,6 +171,7 @@ data NFTMetadataFile = NFTMetadataFile { name :: Text , mediaType :: MediaType , src :: Network.URI + , additionalProperties :: Map Text Metadata } deriving stock (Show, Eq, Ord, Generic) deriving (Binary, Variations) @@ -188,11 +189,19 @@ parseJsonUri (Text.unpack -> s) = maybe (fail $ s <> " is not a valid URI!") pure $ Network.parseURI s instance Aeson.FromJSON NFTMetadataFile where - parseJSON = Aeson.withObject "NFTMetadataFile" \x -> + parseJSON = Aeson.withObject "NFTMetadataFile" \x -> do + let additionalProperties = + Map.mapKeys Key.toText . Map.withoutKeys (Aeson.toMap x) $ + Set.fromList + [ "name" + , "mediaType" + , "src" + ] NFTMetadataFile <$> x .: "name" <*> x .: "mediaType" <*> (parseJsonUri =<< x .: "src") + <*> forWithKey additionalProperties \key value -> Aeson.parseJSON value Aeson.Types.Key (Key.fromText key) data RoleTokenMetadata = RoleTokenMetadata { name :: Text @@ -269,6 +278,7 @@ decodeRoleTokenMetadata = parseNFTMetadataDetails name <- parseMetadataText =<< Map.lookup "name" textKeyMap mediaType <- parseMediaType =<< Map.lookup "mediaType" textKeyMap src <- Network.parseURI . Text.unpack =<< parseSplittableText =<< Map.lookup "src" textKeyMap + let additionalProperties = Map.withoutKeys textKeyMap $ Set.fromList ["name", "mediaType", "src"] Just $ NFTMetadataFile{..} parseMediaType :: Metadata -> Maybe MediaType