packages feed

blockfrost-api 0.8.1.0 → 0.9.0.0

raw patch · 23 files changed

+928/−41 lines, 23 filesdep ~servantPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: servant

API changes (from Hackage documentation)

- Blockfrost.Lens: class HasOnchainMetadata s a | s -> a
- Blockfrost.Lens: instance Blockfrost.Lens.HasImage Blockfrost.Types.Cardano.Assets.AssetOnChainMetadata Data.Text.Internal.Text
- Blockfrost.Lens: instance Blockfrost.Lens.HasName Blockfrost.Types.Cardano.Assets.AssetOnChainMetadata Data.Text.Internal.Text
- Blockfrost.Lens: instance Blockfrost.Lens.HasOnchainMetadata Blockfrost.Types.Cardano.Assets.AssetDetails (GHC.Maybe.Maybe Blockfrost.Types.Cardano.Assets.AssetOnChainMetadata)
- Blockfrost.Lens: onchainMetadata :: HasOnchainMetadata s a => Lens' s a
- Blockfrost.Types.Cardano.Assets: [_assetDetailsOnchainMetadata] :: AssetDetails -> Maybe AssetOnChainMetadata
+ Blockfrost.Auth: Sanchonet :: Env
+ Blockfrost.Env: Sanchonet :: Env
+ Blockfrost.Lens: class HasFiles s a | s -> a
+ Blockfrost.Lens: class HasMediaType s a | s -> a
+ Blockfrost.Lens: class HasOnchainMetadataExtra s a | s -> a
+ Blockfrost.Lens: class HasOnchainMetadataValue s a | s -> a
+ Blockfrost.Lens: class HasOnchainStandardMetadata s a | s -> a
+ Blockfrost.Lens: files :: HasFiles s a => Lens' s a
+ Blockfrost.Lens: instance Blockfrost.Lens.HasDescription Blockfrost.Types.Cardano.Assets.AssetOnChainMetadata (GHC.Maybe.Maybe Data.Text.Internal.Text)
+ Blockfrost.Lens: instance Blockfrost.Lens.HasFiles Blockfrost.Types.Cardano.Assets.AssetOnChainMetadata (GHC.Maybe.Maybe [Blockfrost.Types.Cardano.Assets.MetadataMediaFile])
+ Blockfrost.Lens: instance Blockfrost.Lens.HasImage Blockfrost.Types.Cardano.Assets.AssetOnChainMetadata (GHC.Maybe.Maybe Data.Text.Internal.Text)
+ Blockfrost.Lens: instance Blockfrost.Lens.HasMediaType Blockfrost.Types.Cardano.Assets.AssetOnChainMetadata (GHC.Maybe.Maybe Data.Text.Internal.Text)
+ Blockfrost.Lens: instance Blockfrost.Lens.HasName Blockfrost.Types.Cardano.Assets.AssetOnChainMetadata (GHC.Maybe.Maybe Data.Text.Internal.Text)
+ Blockfrost.Lens: instance Blockfrost.Lens.HasOnchainMetadataExtra Blockfrost.Types.Cardano.Assets.AssetDetails (GHC.Maybe.Maybe Data.Text.Internal.Text)
+ Blockfrost.Lens: instance Blockfrost.Lens.HasOnchainMetadataValue Blockfrost.Types.Cardano.Assets.AssetDetails (GHC.Maybe.Maybe Data.Aeson.Types.Internal.Value)
+ Blockfrost.Lens: instance Blockfrost.Lens.HasOnchainStandardMetadata Blockfrost.Types.Cardano.Assets.AssetDetails (GHC.Maybe.Maybe Blockfrost.Types.Cardano.Assets.AssetOnChainMetadata)
+ Blockfrost.Lens: mediaType :: HasMediaType s a => Lens' s a
+ Blockfrost.Lens: onchainMetadataExtra :: HasOnchainMetadataExtra s a => Lens' s a
+ Blockfrost.Lens: onchainMetadataValue :: HasOnchainMetadataValue s a => Lens' s a
+ Blockfrost.Lens: onchainStandardMetadata :: HasOnchainStandardMetadata s a => Lens' s a
+ Blockfrost.Types.Cardano.Accounts: AddressAssociatedTotal :: Address -> [Amount] -> [Amount] -> Integer -> AddressAssociatedTotal
+ Blockfrost.Types.Cardano.Accounts: [_addressAssociatedTotalReceivedSum] :: AddressAssociatedTotal -> [Amount]
+ Blockfrost.Types.Cardano.Accounts: [_addressAssociatedTotalSentSum] :: AddressAssociatedTotal -> [Amount]
+ Blockfrost.Types.Cardano.Accounts: [_addressAssociatedTotalStakeAddress] :: AddressAssociatedTotal -> Address
+ Blockfrost.Types.Cardano.Accounts: [_addressAssociatedTotalTxCount] :: AddressAssociatedTotal -> Integer
+ Blockfrost.Types.Cardano.Accounts: data AddressAssociatedTotal
+ Blockfrost.Types.Cardano.Accounts: instance Data.Aeson.Types.FromJSON.FromJSON Blockfrost.Types.Cardano.Accounts.AddressAssociatedTotal
+ Blockfrost.Types.Cardano.Accounts: instance Data.Aeson.Types.ToJSON.ToJSON Blockfrost.Types.Cardano.Accounts.AddressAssociatedTotal
+ Blockfrost.Types.Cardano.Accounts: instance GHC.Classes.Eq Blockfrost.Types.Cardano.Accounts.AddressAssociatedTotal
+ Blockfrost.Types.Cardano.Accounts: instance GHC.Generics.Generic Blockfrost.Types.Cardano.Accounts.AddressAssociatedTotal
+ Blockfrost.Types.Cardano.Accounts: instance GHC.Show.Show Blockfrost.Types.Cardano.Accounts.AddressAssociatedTotal
+ Blockfrost.Types.Cardano.Accounts: instance Servant.Docs.Internal.ToSample Blockfrost.Types.Cardano.Accounts.AddressAssociatedTotal
+ Blockfrost.Types.Cardano.Addresses: AddressInfoExtended :: Address -> [AmountExtended] -> Maybe Address -> AddressType -> Bool -> AddressInfoExtended
+ Blockfrost.Types.Cardano.Addresses: [_addressInfoExtendedAddress] :: AddressInfoExtended -> Address
+ Blockfrost.Types.Cardano.Addresses: [_addressInfoExtendedAmount] :: AddressInfoExtended -> [AmountExtended]
+ Blockfrost.Types.Cardano.Addresses: [_addressInfoExtendedScript] :: AddressInfoExtended -> Bool
+ Blockfrost.Types.Cardano.Addresses: [_addressInfoExtendedStakeAddress] :: AddressInfoExtended -> Maybe Address
+ Blockfrost.Types.Cardano.Addresses: [_addressInfoExtendedType] :: AddressInfoExtended -> AddressType
+ Blockfrost.Types.Cardano.Addresses: data AddressInfoExtended
+ Blockfrost.Types.Cardano.Addresses: instance Data.Aeson.Types.FromJSON.FromJSON Blockfrost.Types.Cardano.Addresses.AddressInfoExtended
+ Blockfrost.Types.Cardano.Addresses: instance Data.Aeson.Types.ToJSON.ToJSON Blockfrost.Types.Cardano.Addresses.AddressInfoExtended
+ Blockfrost.Types.Cardano.Addresses: instance GHC.Classes.Eq Blockfrost.Types.Cardano.Addresses.AddressInfoExtended
+ Blockfrost.Types.Cardano.Addresses: instance GHC.Generics.Generic Blockfrost.Types.Cardano.Addresses.AddressInfoExtended
+ Blockfrost.Types.Cardano.Addresses: instance GHC.Show.Show Blockfrost.Types.Cardano.Addresses.AddressInfoExtended
+ Blockfrost.Types.Cardano.Addresses: instance Servant.Docs.Internal.ToSample Blockfrost.Types.Cardano.Addresses.AddressInfoExtended
+ Blockfrost.Types.Cardano.Assets: MetadataMediaFile :: Maybe Text -> Maybe Text -> Maybe Text -> MetadataMediaFile
+ Blockfrost.Types.Cardano.Assets: [_assetDetailsOnchainMetadataExtra] :: AssetDetails -> Maybe Text
+ Blockfrost.Types.Cardano.Assets: [_assetDetailsOnchainMetadataValue] :: AssetDetails -> Maybe Value
+ Blockfrost.Types.Cardano.Assets: [_assetDetailsOnchainStandardMetadata] :: AssetDetails -> Maybe AssetOnChainMetadata
+ Blockfrost.Types.Cardano.Assets: [_assetOnChainMetadataDescription] :: AssetOnChainMetadata -> Maybe Text
+ Blockfrost.Types.Cardano.Assets: [_assetOnChainMetadataFiles] :: AssetOnChainMetadata -> Maybe [MetadataMediaFile]
+ Blockfrost.Types.Cardano.Assets: [_assetOnChainMetadataMediaType] :: AssetOnChainMetadata -> Maybe Text
+ Blockfrost.Types.Cardano.Assets: [_metadataMediaFileMediaType] :: MetadataMediaFile -> Maybe Text
+ Blockfrost.Types.Cardano.Assets: [_metadataMediaFileName] :: MetadataMediaFile -> Maybe Text
+ Blockfrost.Types.Cardano.Assets: [_metadataMediaFileSrc] :: MetadataMediaFile -> Maybe Text
+ Blockfrost.Types.Cardano.Assets: data MetadataMediaFile
+ Blockfrost.Types.Cardano.Assets: instance Data.Aeson.Types.FromJSON.FromJSON Blockfrost.Types.Cardano.Assets.MetadataMediaFile
+ Blockfrost.Types.Cardano.Assets: instance Data.Aeson.Types.ToJSON.ToJSON Blockfrost.Types.Cardano.Assets.MetadataMediaFile
+ Blockfrost.Types.Cardano.Assets: instance Deriving.Aeson.StringModifier Blockfrost.Types.Cardano.Assets.LowerHead
+ Blockfrost.Types.Cardano.Assets: instance GHC.Classes.Eq Blockfrost.Types.Cardano.Assets.MetadataMediaFile
+ Blockfrost.Types.Cardano.Assets: instance GHC.Generics.Generic Blockfrost.Types.Cardano.Assets.MetadataMediaFile
+ Blockfrost.Types.Cardano.Assets: instance GHC.Show.Show Blockfrost.Types.Cardano.Assets.MetadataMediaFile
+ Blockfrost.Types.Cardano.Assets: instance Servant.Docs.Internal.ToSample Blockfrost.Types.Cardano.Assets.MetadataMediaFile
+ Blockfrost.Types.Cardano.Assets: parseStandardMetadata :: Maybe Value -> Maybe AssetOnChainMetadata
+ Blockfrost.Types.Cardano.Assets: parseStandardMetadataInDetails :: AssetDetails -> AssetDetails
+ Blockfrost.Types.Cardano.Pools: Pool :: PoolId -> Text -> Lovelaces -> Lovelaces -> Pool
+ Blockfrost.Types.Cardano.Pools: [_poolActiveStake] :: Pool -> Lovelaces
+ Blockfrost.Types.Cardano.Pools: [_poolHex] :: Pool -> Text
+ Blockfrost.Types.Cardano.Pools: [_poolLiveStake] :: Pool -> Lovelaces
+ Blockfrost.Types.Cardano.Pools: [_poolPoolId] :: Pool -> PoolId
+ Blockfrost.Types.Cardano.Pools: data Pool
+ Blockfrost.Types.Cardano.Pools: instance Data.Aeson.Types.FromJSON.FromJSON Blockfrost.Types.Cardano.Pools.Pool
+ Blockfrost.Types.Cardano.Pools: instance Data.Aeson.Types.ToJSON.ToJSON Blockfrost.Types.Cardano.Pools.Pool
+ Blockfrost.Types.Cardano.Pools: instance GHC.Classes.Eq Blockfrost.Types.Cardano.Pools.Pool
+ Blockfrost.Types.Cardano.Pools: instance GHC.Generics.Generic Blockfrost.Types.Cardano.Pools.Pool
+ Blockfrost.Types.Cardano.Pools: instance GHC.Show.Show Blockfrost.Types.Cardano.Pools.Pool
+ Blockfrost.Types.Cardano.Pools: instance Servant.Docs.Internal.ToSample Blockfrost.Types.Cardano.Pools.Pool
+ Blockfrost.Types.Cardano.Utils: DerivedAddress :: Text -> Integer -> Integer -> Text -> DerivedAddress
+ Blockfrost.Types.Cardano.Utils: TxEval :: [TxEvalResult] -> TxEval
+ Blockfrost.Types.Cardano.Utils: TxEvalBudget :: Integer -> Integer -> TxEvalBudget
+ Blockfrost.Types.Cardano.Utils: TxEvalInput :: CBORString -> Value -> TxEvalInput
+ Blockfrost.Types.Cardano.Utils: TxEvalResult :: Text -> TxEvalBudget -> TxEvalResult
+ Blockfrost.Types.Cardano.Utils: [_derivedAddressAddress] :: DerivedAddress -> Text
+ Blockfrost.Types.Cardano.Utils: [_derivedAddressIndex] :: DerivedAddress -> Integer
+ Blockfrost.Types.Cardano.Utils: [_derivedAddressRole] :: DerivedAddress -> Integer
+ Blockfrost.Types.Cardano.Utils: [_derivedAddressXpub] :: DerivedAddress -> Text
+ Blockfrost.Types.Cardano.Utils: [_txEvalBudgetCPU] :: TxEvalBudget -> Integer
+ Blockfrost.Types.Cardano.Utils: [_txEvalBudgetMemory] :: TxEvalBudget -> Integer
+ Blockfrost.Types.Cardano.Utils: [_txEvalInputAdditionalUtxoSet] :: TxEvalInput -> Value
+ Blockfrost.Types.Cardano.Utils: [_txEvalInputCbor] :: TxEvalInput -> CBORString
+ Blockfrost.Types.Cardano.Utils: [_txEvalResultBudget] :: TxEvalResult -> TxEvalBudget
+ Blockfrost.Types.Cardano.Utils: [_txEvalResultValidator] :: TxEvalResult -> Text
+ Blockfrost.Types.Cardano.Utils: [_txEvalResult] :: TxEval -> [TxEvalResult]
+ Blockfrost.Types.Cardano.Utils: data DerivedAddress
+ Blockfrost.Types.Cardano.Utils: data TxEvalBudget
+ Blockfrost.Types.Cardano.Utils: data TxEvalInput
+ Blockfrost.Types.Cardano.Utils: data TxEvalResult
+ Blockfrost.Types.Cardano.Utils: evalSample :: TxEval
+ Blockfrost.Types.Cardano.Utils: instance Data.Aeson.Types.FromJSON.FromJSON Blockfrost.Types.Cardano.Utils.DerivedAddress
+ Blockfrost.Types.Cardano.Utils: instance Data.Aeson.Types.FromJSON.FromJSON Blockfrost.Types.Cardano.Utils.TxEval
+ Blockfrost.Types.Cardano.Utils: instance Data.Aeson.Types.FromJSON.FromJSON Blockfrost.Types.Cardano.Utils.TxEvalBudget
+ Blockfrost.Types.Cardano.Utils: instance Data.Aeson.Types.FromJSON.FromJSON Blockfrost.Types.Cardano.Utils.TxEvalInput
+ Blockfrost.Types.Cardano.Utils: instance Data.Aeson.Types.FromJSON.FromJSON Blockfrost.Types.Cardano.Utils.TxEvalResult
+ Blockfrost.Types.Cardano.Utils: instance Data.Aeson.Types.ToJSON.ToJSON Blockfrost.Types.Cardano.Utils.DerivedAddress
+ Blockfrost.Types.Cardano.Utils: instance Data.Aeson.Types.ToJSON.ToJSON Blockfrost.Types.Cardano.Utils.TxEval
+ Blockfrost.Types.Cardano.Utils: instance Data.Aeson.Types.ToJSON.ToJSON Blockfrost.Types.Cardano.Utils.TxEvalBudget
+ Blockfrost.Types.Cardano.Utils: instance Data.Aeson.Types.ToJSON.ToJSON Blockfrost.Types.Cardano.Utils.TxEvalInput
+ Blockfrost.Types.Cardano.Utils: instance Data.Aeson.Types.ToJSON.ToJSON Blockfrost.Types.Cardano.Utils.TxEvalResult
+ Blockfrost.Types.Cardano.Utils: instance Deriving.Aeson.StringModifier Blockfrost.Types.Cardano.Utils.LowerLeading
+ Blockfrost.Types.Cardano.Utils: instance GHC.Classes.Eq Blockfrost.Types.Cardano.Utils.DerivedAddress
+ Blockfrost.Types.Cardano.Utils: instance GHC.Classes.Eq Blockfrost.Types.Cardano.Utils.TxEval
+ Blockfrost.Types.Cardano.Utils: instance GHC.Classes.Eq Blockfrost.Types.Cardano.Utils.TxEvalBudget
+ Blockfrost.Types.Cardano.Utils: instance GHC.Classes.Eq Blockfrost.Types.Cardano.Utils.TxEvalInput
+ Blockfrost.Types.Cardano.Utils: instance GHC.Classes.Eq Blockfrost.Types.Cardano.Utils.TxEvalResult
+ Blockfrost.Types.Cardano.Utils: instance GHC.Generics.Generic Blockfrost.Types.Cardano.Utils.DerivedAddress
+ Blockfrost.Types.Cardano.Utils: instance GHC.Generics.Generic Blockfrost.Types.Cardano.Utils.TxEval
+ Blockfrost.Types.Cardano.Utils: instance GHC.Generics.Generic Blockfrost.Types.Cardano.Utils.TxEvalBudget
+ Blockfrost.Types.Cardano.Utils: instance GHC.Generics.Generic Blockfrost.Types.Cardano.Utils.TxEvalInput
+ Blockfrost.Types.Cardano.Utils: instance GHC.Generics.Generic Blockfrost.Types.Cardano.Utils.TxEvalResult
+ Blockfrost.Types.Cardano.Utils: instance GHC.Show.Show Blockfrost.Types.Cardano.Utils.DerivedAddress
+ Blockfrost.Types.Cardano.Utils: instance GHC.Show.Show Blockfrost.Types.Cardano.Utils.TxEval
+ Blockfrost.Types.Cardano.Utils: instance GHC.Show.Show Blockfrost.Types.Cardano.Utils.TxEvalBudget
+ Blockfrost.Types.Cardano.Utils: instance GHC.Show.Show Blockfrost.Types.Cardano.Utils.TxEvalInput
+ Blockfrost.Types.Cardano.Utils: instance GHC.Show.Show Blockfrost.Types.Cardano.Utils.TxEvalResult
+ Blockfrost.Types.Cardano.Utils: instance Servant.Docs.Internal.ToSample Blockfrost.Types.Cardano.Utils.DerivedAddress
+ Blockfrost.Types.Cardano.Utils: instance Servant.Docs.Internal.ToSample Blockfrost.Types.Cardano.Utils.TxEval
+ Blockfrost.Types.Cardano.Utils: instance Servant.Docs.Internal.ToSample Blockfrost.Types.Cardano.Utils.TxEvalBudget
+ Blockfrost.Types.Cardano.Utils: instance Servant.Docs.Internal.ToSample Blockfrost.Types.Cardano.Utils.TxEvalInput
+ Blockfrost.Types.Cardano.Utils: instance Servant.Docs.Internal.ToSample Blockfrost.Types.Cardano.Utils.TxEvalResult
+ Blockfrost.Types.Cardano.Utils: newtype TxEval
+ Blockfrost.Types.Cardano.Utils: resultSample :: TxEvalResult
+ Blockfrost.Types.Shared.Amount: AdaAmountExtended :: Lovelaces -> AmountExtended
+ Blockfrost.Types.Shared.Amount: AssetAmountExtended :: Maybe Int -> Bool -> SomeDiscrete -> AmountExtended
+ Blockfrost.Types.Shared.Amount: [assetAmountExtendedDecimals] :: AmountExtended -> Maybe Int
+ Blockfrost.Types.Shared.Amount: [assetAmountExtendedHasNftOnchainMetadata] :: AmountExtended -> Bool
+ Blockfrost.Types.Shared.Amount: [assetAmountExtendedValue] :: AmountExtended -> SomeDiscrete
+ Blockfrost.Types.Shared.Amount: data AmountExtended
+ Blockfrost.Types.Shared.Amount: instance Data.Aeson.Types.FromJSON.FromJSON Blockfrost.Types.Shared.Amount.AmountExtended
+ Blockfrost.Types.Shared.Amount: instance Data.Aeson.Types.ToJSON.ToJSON Blockfrost.Types.Shared.Amount.AmountExtended
+ Blockfrost.Types.Shared.Amount: instance GHC.Classes.Eq Blockfrost.Types.Shared.Amount.AmountExtended
+ Blockfrost.Types.Shared.Amount: instance GHC.Classes.Ord Blockfrost.Types.Shared.Amount.AmountExtended
+ Blockfrost.Types.Shared.Amount: instance GHC.Generics.Generic Blockfrost.Types.Shared.Amount.AmountExtended
+ Blockfrost.Types.Shared.Amount: instance GHC.Show.Show Blockfrost.Types.Shared.Amount.AmountExtended
+ Blockfrost.Types.Shared.Amount: instance Servant.Docs.Internal.ToSample Blockfrost.Types.Shared.Amount.AmountExtended
+ Blockfrost.Types.Shared.CBOR: instance Data.Aeson.Types.FromJSON.FromJSON Blockfrost.Types.Shared.CBOR.CBORString
+ Blockfrost.Types.Shared.CBOR: instance Data.Aeson.Types.ToJSON.ToJSON Blockfrost.Types.Shared.CBOR.CBORString
- Blockfrost.Types.Cardano.Assets: AssetDetails :: Text -> PolicyId -> Maybe Text -> Text -> Quantity -> TxHash -> Integer -> Maybe AssetOnChainMetadata -> Maybe AssetMetadata -> AssetDetails
+ Blockfrost.Types.Cardano.Assets: AssetDetails :: Text -> PolicyId -> Maybe Text -> Text -> Quantity -> TxHash -> Integer -> Maybe Value -> Maybe AssetOnChainMetadata -> Maybe AssetMetadata -> Maybe Text -> AssetDetails
- Blockfrost.Types.Cardano.Assets: AssetOnChainMetadata :: Text -> Text -> AssetOnChainMetadata
+ Blockfrost.Types.Cardano.Assets: AssetOnChainMetadata :: Maybe Text -> Maybe Text -> Maybe Text -> Maybe Text -> Maybe [MetadataMediaFile] -> AssetOnChainMetadata
- Blockfrost.Types.Cardano.Assets: [_assetOnChainMetadataImage] :: AssetOnChainMetadata -> Text
+ Blockfrost.Types.Cardano.Assets: [_assetOnChainMetadataImage] :: AssetOnChainMetadata -> Maybe Text
- Blockfrost.Types.Cardano.Assets: [_assetOnChainMetadataName] :: AssetOnChainMetadata -> Text
+ Blockfrost.Types.Cardano.Assets: [_assetOnChainMetadataName] :: AssetOnChainMetadata -> Maybe Text

Files

CHANGELOG.md view
@@ -1,3 +1,19 @@+# Version [0.9.0.0](https://github.com/blockfrost/blockfrost-haskell/compare/api-0.8.1.0...api-0.9.0.0) (2023-12-18)++* Allow servant `0.20` [#41](https://github.com/blockfrost/blockfrost-haskell/pull/41)+* Additions [#43](https://github.com/blockfrost/blockfrost-haskell/pull/43)+  * `Env` enum extended with `Sanchonet` for `cardano-sanchonet` network+  * `/accounts/:stake_address/addresses/total` endpoint and `AddressAssociatedTotal` type+  * `/addresses/:address/extended` endpoint and `AddressInfoExtended` type (uses `AmountExtended` type)+  * `/pools/extended` endpoint and `Pool` type+  * `/utils` API+    * `/utils/addresses/xpub/:xpub/:role/:index` endpoint and `DerivedAddress` type+    * `/utils/txs/evaluate` endpoint+    * `/utils/txs/evaluate/utxos` endpoint+    * `TxEval`, `TxEvalResult`, `TxEvalBudget`, `TxEvalInput` types for the two above+* Better metadata handling [#40](https://github.com/blockfrost/blockfrost-haskell/pull/40)+  * Adds `onchainMetadataExtra` and `onchainMetadataValue` fields for `AssetDetails`+ # Version [0.8.1.0](https://github.com/blockfrost/blockfrost-haskell/compare/api-0.8.0.0...api-0.8.1.0) (2023-09-18)  * Added `address` field to `AddressUtxo` [#38](https://github.com/blockfrost/blockfrost-haskell/pull/38)
blockfrost-api.cabal view
@@ -1,6 +1,6 @@ cabal-version:       2.2 name:                blockfrost-api-version:             0.8.1.0+version:             0.9.0.0 synopsis:            API definitions for blockfrost.io description:         Core types and Servant API description homepage:            https://github.com/blockfrost/blockfrost-haskell@@ -13,9 +13,10 @@ build-type:          Simple  extra-source-files:-    CHANGELOG.md     LICENSE     README.md+extra-doc-files:+    CHANGELOG.md  flag BuildFast      Default: True@@ -72,6 +73,7 @@                       , Blockfrost.API.Cardano.Pools                       , Blockfrost.API.Cardano.Scripts                       , Blockfrost.API.Cardano.Transactions+                      , Blockfrost.API.Cardano.Utils                       , Blockfrost.API.IPFS                       , Blockfrost.API.NutLink                       , Blockfrost.Auth@@ -92,6 +94,7 @@                       , Blockfrost.Types.Cardano.Pools                       , Blockfrost.Types.Cardano.Scripts                       , Blockfrost.Types.Cardano.Transactions+                      , Blockfrost.Types.Cardano.Utils                       , Blockfrost.Types.IPFS                       , Blockfrost.Types.NutLink                       , Blockfrost.Types.Shared@@ -130,7 +133,7 @@                       , deriving-aeson                       , lens                     >= 5.0 && < 5.3                       , template-haskell-                      , servant                  >= 0.18 && < 0.20+                      , servant                  >= 0.18 && < 0.21                       , servant-docs                       , servant-multipart-api                       , safe-money               >= 0.9 && < 0.10@@ -153,6 +156,7 @@                      , Cardano.Pools                      , Cardano.Scripts                      , Cardano.Transactions+                     , Cardano.Utils                      , IPFS                      , NutLink   build-depends:       base >= 4.7 && < 5
src/Blockfrost/API.hs view
@@ -132,6 +132,11 @@       :> "submit"       :> ReqBody '[CBOR] CBORString       :> Post '[JSON] TxHash+    , _utils+      :: route+      :- "utils"+      :> Tag "Cardano » Utilities"+      :> ToServantApi UtilsAPI     } deriving (Generic)  type ServantBlockfrostAPI = ToServantApi BlockfrostAPI
src/Blockfrost/API/Cardano.hs view
@@ -14,6 +14,7 @@   , module Blockfrost.API.Cardano.Pools   , module Blockfrost.API.Cardano.Scripts   , module Blockfrost.API.Cardano.Transactions+  , module Blockfrost.API.Cardano.Utils   ) where  import Blockfrost.API.Cardano.Accounts@@ -27,3 +28,4 @@ import Blockfrost.API.Cardano.Pools import Blockfrost.API.Cardano.Scripts import Blockfrost.API.Cardano.Transactions+import Blockfrost.API.Cardano.Utils
src/Blockfrost/API/Cardano/Accounts.hs view
@@ -95,4 +95,15 @@         :> Pagination         :> Sorting         :> Get '[JSON] [Amount]+     , _accountAssociatedTotal+        :: route+        :- Summary "Detailed information about account associated addresses"+        :> Description "Obtain summed details about all addresses associated with a given account. \+                        \Be careful, as an account could be part of a mangled address and does not \+                        \necessarily mean the addresses are owned by user as the account."+        :> Capture "stake_address" Address+        :> "addresses"+        :> "total"+        :> Get '[JSON] AddressAssociatedTotal+     } deriving (Generic)
src/Blockfrost/API/Cardano/Addresses.hs view
@@ -22,6 +22,13 @@         :> Description "Obtain information about a specific address."         :> Capture "address" Address         :> Get '[JSON] AddressInfo+    , _addressInfoExtended+        :: route+        :- Summary "Specific address - extended"+        :> Description "Obtain extended information about a specific address."+        :> Capture "address" Address+        :> "extended"+        :> Get '[JSON] AddressInfoExtended     , _addressDetails         :: route         :- Summary "Address details"
src/Blockfrost/API/Cardano/Pools.hs view
@@ -23,6 +23,14 @@         :> Pagination         :> Sorting         :> Get '[JSON] [PoolId]+    , _listPoolsExtended+        :: route+        :- Summary "List of stake pools with additional information"+        :> Description "List of registered stake pools with additional information."+        :> "extended"+        :> Pagination+        :> Sorting+        :> Get '[JSON] [Pool]     , _listRetiredPools         :: route         :- Summary "List of retired stake pools"
+ src/Blockfrost/API/Cardano/Utils.hs view
@@ -0,0 +1,50 @@+-- | Cardano utility endpoints++{-# OPTIONS_HADDOCK hide #-}++module Blockfrost.API.Cardano.Utils+  where++import Data.Text+import Servant.API+import Servant.API.Generic++import Blockfrost.Types.Cardano.Utils+import Blockfrost.Types.Shared.CBOR++data UtilsAPI route =+  UtilsAPI+    {+      _deriveAddr+        :: route+        :- Summary "Derive an address"+        :> Description "Derive Shelley address from an xpub."+        :> "addresses"+        :> "xpub"+        :> Capture "xpub" Text+        :> Capture "role" Integer+        :> Capture "Index" Integer+        :> Get '[JSON] DerivedAddress++    , _txEvaluate+        :: route+        :- Summary "Submit a transaction for execution units evaluation"+        :> Description "Submit an already serialized transaction to evaluate \+                       \how much execution units it requires."+        :> "txs"+        :> "evaluate"+        :> ReqBody '[CBOR] CBORString+        :> Post '[JSON] TxEval++    , _txEvaluateUTXOs+        :: route+        :- Summary "Submit a transaction for execution units evaluation (additional UTXO set)"+        :> Description "Submit a JSON payload with transaction CBOR and additional UTXO set \+                       \to evaluate how much execution units it requires."+        :> "txs"+        :> "evaluate"+        :> "utxos"+        :> ReqBody '[JSON] TxEvalInput+        :> Post '[JSON] TxEval++    } deriving (Generic)
src/Blockfrost/Env.hs view
@@ -20,6 +20,7 @@   | Testnet   | Preprod   | Preview+  | Sanchonet   | Localhost   deriving (Eq, Read, Show, Ord, Generic) @@ -30,4 +31,4 @@   Nothing ->     Left       $ "Unknown environment: `" <> tEnv <> "`"-      <> " expecting one of `ipfs`, `mainnet`, `testnet`, `localhost`"+      <> " expecting one of `ipfs`, `mainnet`, `testnet`, `preprod`, `preview`, `sanchonet`, `localhost`"
src/Blockfrost/Types/Cardano.hs view
@@ -12,6 +12,7 @@   , module Blockfrost.Types.Cardano.Pools   , module Blockfrost.Types.Cardano.Scripts   , module Blockfrost.Types.Cardano.Transactions+  , module Blockfrost.Types.Cardano.Utils   ) where  import Blockfrost.Types.Cardano.Accounts@@ -25,3 +26,4 @@ import Blockfrost.Types.Cardano.Pools import Blockfrost.Types.Cardano.Scripts import Blockfrost.Types.Cardano.Transactions+import Blockfrost.Types.Cardano.Utils
src/Blockfrost/Types/Cardano/Accounts.hs view
@@ -11,10 +11,12 @@   , AccountWithdrawal (..)   , AccountMir (..)   , AddressAssociated (..)+  , AddressAssociatedTotal (..)   ) where  import Blockfrost.Types.Shared import Deriving.Aeson+import qualified Money import Servant.Docs (ToSample (..), samples, singleSample)  -- | Information about an account, identified by its stake address@@ -230,3 +232,36 @@     [ AddressAssociated "addr1qx2kd28nq8ac5prwg32hhvudlwggpgfp8utlyqxu6wqgz62f79qsdmm5dsknt9ecr5w468r9ey0fxwkdrwh08ly3tu9sy0f4qd"     , AddressAssociated "addr1q8j55h253zcvl326sk5qdt2n8z7eghzspe0ekxgncr796s2f79qsdmm5dsknt9ecr5w468r9ey0fxwkdrwh08ly3tu9sjmd35m"     ]++-- | Detailed information about account associated addresses+data AddressAssociatedTotal = AddressAssociatedTotal {+    _addressAssociatedTotalStakeAddress :: Address -- ^ Bech32 encoded address+  , _addressAssociatedTotalReceivedSum  :: [Amount]+  , _addressAssociatedTotalSentSum      :: [Amount]+  , _addressAssociatedTotalTxCount      :: Integer -- ^ Count of all transactions for all addresses associated with the account+  } deriving stock (Show, Eq, Generic)+  deriving (FromJSON, ToJSON)+  via CustomJSON '[FieldLabelModifier '[StripPrefix "_addressAssociatedTotal", CamelToSnake]] AddressAssociatedTotal++instance ToSample AddressAssociatedTotal where+  toSamples = pure $ singleSample+    AddressAssociatedTotal+      { _addressAssociatedTotalStakeAddress = "stake1u9l5q5jwgelgagzyt6nuaasefgmn8pd25c8e9qpeprq0tdcp0e3uk"+      , _addressAssociatedTotalReceivedSum =+          [ AdaAmount 42000000+          , AssetAmount+              $ Money.mkSomeDiscrete+                  "b0d07d45fe9514f80213f4020e5a61241458be626841cde717cb38a76e7574636f696e"+                   unitScale+                   12+          ]+      , _addressAssociatedTotalSentSum =+          [ AdaAmount 123+          , AssetAmount+              $ Money.mkSomeDiscrete+                  "b0d07d45fe9514f80213f4020e5a61241458be626841cde717cb38a76e7574636f696e"+                   unitScale+                   1+          ]+      , _addressAssociatedTotalTxCount = 2+      }
src/Blockfrost/Types/Cardano/Addresses.hs view
@@ -2,6 +2,7 @@  module Blockfrost.Types.Cardano.Addresses   ( AddressInfo (..)+  , AddressInfoExtended (..)   , AddressType (..)   , AddressDetails (..)   , AddressUtxo (..)@@ -41,6 +42,38 @@       , _addressInfoStakeAddress = pure "stake1ux3g2c9dx2nhhehyrezyxpkstartcqmu9hk63qgfkccw5rqttygt7"       , _addressInfoType = Shelley       , _addressInfoScript = False+      }++-- | Information about Cardano address+data AddressInfoExtended = AddressInfoExtended+  { _addressInfoExtendedAddress      :: Address -- ^ Bech32 encoded addresses+  , _addressInfoExtendedAmount       :: [AmountExtended] -- ^ Lovelaces or tokens stored on this address+  , _addressInfoExtendedStakeAddress :: Maybe Address -- ^ Stake address that controls the key+  , _addressInfoExtendedType         :: AddressType -- ^ Address era+  , _addressInfoExtendedScript       :: Bool -- ^ True if this is a script address+  } deriving stock (Show, Eq, Generic)+  deriving (FromJSON, ToJSON)+  via CustomJSON '[FieldLabelModifier '[StripPrefix "_addressInfoExtended", CamelToSnake]] AddressInfoExtended++instance ToSample AddressInfoExtended where+  toSamples = pure $ singleSample+    AddressInfoExtended+      { _addressInfoExtendedAddress = "addr1qxqs59lphg8g6qndelq8xwqn60ag3aeyfcp33c2kdp46a09re5df3pzwwmyq946axfcejy5n4x0y99wqpgtp2gd0k09qsgy6pz"+      , _addressInfoExtendedAmount =+        [ AdaAmountExtended 42000000+        , AssetAmountExtended+            { assetAmountExtendedDecimals              = Nothing+            , assetAmountExtendedHasNftOnchainMetadata = True+            , assetAmountExtendedValue =+                Money.toSomeDiscrete+                (12 :: Money.Discrete'+                          "b0d07d45fe9514f80213f4020e5a61241458be626841cde717cb38a76e7574636f696e"+                          '(1,1))+            }+        ]+      , _addressInfoExtendedStakeAddress = pure "stake1ux3g2c9dx2nhhehyrezyxpkstartcqmu9hk63qgfkccw5rqttygt7"+      , _addressInfoExtendedType = Shelley+      , _addressInfoExtendedScript = False       }  -- | Type (era) of an address
src/Blockfrost/Types/Cardano/Assets.hs view
@@ -4,6 +4,9 @@   ( AssetInfo (..)   , AssetDetails (..)   , AssetOnChainMetadata (..)+  , MetadataMediaFile (..)+  , parseStandardMetadata+  , parseStandardMetadataInDetails   , AssetMetadata (..)   , AssetHistory (..)   , AssetAction (..)@@ -12,9 +15,15 @@   ) where  import Blockfrost.Types.Shared+import Data.Aeson (Value (..), FromJSON(parseJSON))+import Data.Aeson.Types (parseMaybe)+import Data.Aeson.KeyMap (fromList)+import Data.Char (toLower) import Data.Text (Text)+import qualified Data.Vector as V (singleton) import Deriving.Aeson import Servant.Docs (ToSample (..), samples, singleSample)+import Prelude hiding (String)  -- | Asset information, result of listing assets data AssetInfo = AssetInfo@@ -41,23 +50,57 @@         }     ] +-- CIP25 uses camelCase, so we need this to derive appropriate instances+data LowerHead++instance StringModifier LowerHead where+  getStringModifier (f:rest) = toLower f : rest+  getStringModifier [] = error "Empty field name"++-- | Additional media files (accordingly to CIP25 and CIP68)+data MetadataMediaFile = MetadataMediaFile+  { _metadataMediaFileName      :: Maybe Text -- ^ file name+  , _metadataMediaFileMediaType :: Maybe Text -- ^ file MIME content-type+  , _metadataMediaFileSrc       :: Maybe Text -- ^ URI of the media file+  }+  deriving stock (Show, Eq, Generic)+  deriving (FromJSON, ToJSON)+  via CustomJSON '[FieldLabelModifier '[StripPrefix "_metadataMediaFile", LowerHead]] MetadataMediaFile++instance ToSample MetadataMediaFile where+  toSamples = pure $ singleSample sampleAssetOnChainMetadataFile++sampleAssetOnChainMetadataFile :: MetadataMediaFile+sampleAssetOnChainMetadataFile =+    MetadataMediaFile+      { _metadataMediaFileName = Just "Detailed image"+      , _metadataMediaFileMediaType = Just "image/png"+      , _metadataMediaFileSrc = Just "ipfs://ipfs/QmfKyJ4tuvHowwKQCbCHj4L5T3fSj8cjs7Aau8V7BWv226"+      }+ -- | On-chain metadata stored in the minting transaction under label 721, -- community discussion around the standard ongoing at https://github.com/cardano-foundation/CIPs/pull/85 data AssetOnChainMetadata = AssetOnChainMetadata-  { _assetOnChainMetadataName  :: Text -- ^ Name of the asset-  , _assetOnChainMetadataImage :: Text -- ^ URI of the associated asset-  -- TODO: in schema has `additionalProperties: true`-  -- so it can carry more arbitrary properties, keep as Value?+  { _assetOnChainMetadataName        :: Maybe Text                -- ^ Name of the asset+  , _assetOnChainMetadataDescription :: Maybe Text                -- ^ Description of the asset+  , _assetOnChainMetadataImage       :: Maybe Text                -- ^ URI of the image, usually IPFS-based+  , _assetOnChainMetadataMediaType   :: Maybe Text                -- ^ image MIME content-type+  , _assetOnChainMetadataFiles       :: Maybe [MetadataMediaFile] -- ^ Additional media files   }   deriving stock (Show, Eq, Generic)   deriving (FromJSON, ToJSON)-  via CustomJSON '[FieldLabelModifier '[StripPrefix "_assetOnChainMetadata", CamelToSnake]] AssetOnChainMetadata+  via CustomJSON '[FieldLabelModifier '[StripPrefix "_assetOnChainMetadata", LowerHead]] AssetOnChainMetadata  instance ToSample AssetOnChainMetadata where-  toSamples = pure $ singleSample-    AssetOnChainMetadata-      { _assetOnChainMetadataName = "My NFT token"-      , _assetOnChainMetadataImage = "ipfs://ipfs/QmfKyJ4tuvHowwKQCbCHj4L5T3fSj8cjs7Aau8V7BWv226"+  toSamples = pure $ singleSample $ sampleAssetOnChainMetadata++sampleAssetOnChainMetadata :: AssetOnChainMetadata+sampleAssetOnChainMetadata = AssetOnChainMetadata+      { _assetOnChainMetadataName = Just "My NFT token"+      , _assetOnChainMetadataDescription = Just "A cool token for joy and fun."+      , _assetOnChainMetadataImage = Just "ipfs://ipfs/QmfKyJ4tuvHowwKQCbCHj4L5T3fSj8cjs7Aau8V7BWv226"+      , _assetOnChainMetadataMediaType = Just "image/png"+      , _assetOnChainMetadataFiles = Just [ sampleAssetOnChainMetadataFile ]       }  -- | Asset metadata obtained from Cardano token registry@@ -87,22 +130,43 @@  -- | Details of an asset data AssetDetails = AssetDetails-  { _assetDetailsAsset             :: Text -- ^ Hex-encoded asset full name-  , _assetDetailsPolicyId          :: PolicyId -- ^ Policy ID of the asset-  , _assetDetailsAssetName         :: Maybe Text -- ^ Hex-encoded asset name of the asset-  , _assetDetailsFingerprint       :: Text -- ^ CIP14 based user-facing fingerprint-  , _assetDetailsQuantity          :: Quantity -- ^ Current asset quantity-  , _assetDetailsInitialMintTxHash :: TxHash -- ^ ID of the initial minting transaction-  , _assetDetailsMintOrBurnCount   :: Integer -- ^ Count of mint and burn transactions-  , _assetDetailsOnchainMetadata   :: Maybe AssetOnChainMetadata-  -- ^ On-chain metadata stored in the minting transaction under label 721,-  -- community discussion around the standard ongoing at https://github.com/cardano-foundation/CIPs/pull/85-  , _assetDetailsMetadata          :: Maybe AssetMetadata+  { _assetDetailsAsset                :: Text -- ^ Hex-encoded asset full name+  , _assetDetailsPolicyId             :: PolicyId -- ^ Policy ID of the asset+  , _assetDetailsAssetName            :: Maybe Text -- ^ Hex-encoded asset name of the asset+  , _assetDetailsFingerprint          :: Text -- ^ CIP14 based user-facing fingerprint+  , _assetDetailsQuantity             :: Quantity -- ^ Current asset quantity+  , _assetDetailsInitialMintTxHash    :: TxHash -- ^ ID of the initial minting transaction+  , _assetDetailsMintOrBurnCount      :: Integer -- ^ Count of mint and burn transactions+  , _assetDetailsOnchainMetadataValue :: Maybe Value+  -- ^ On-chain metadata stored in the minting transaction under label 721 for CIP25+  -- standard or in the first element in the specific constructor in a reference token's+  -- datum for CIP68 standard. In both cases this part is represenatable as JSON+  -- and might be arbitrary, so we keep it as @Value@+  , _assetDetailsOnchainStandardMetadata :: Maybe AssetOnChainMetadata+  -- ^ Some bits of on-chain metadata are considered being "standard" (like name, image and so on).+  -- If they are found in the metadata JSON bundle, this field will contain them.+  , _assetDetailsMetadata             :: Maybe AssetMetadata+  , _assetDetailsOnchainMetadataExtra :: Maybe Text+  -- ^ CIP68 extra metadata plutus data (CBOR-encoded)   }   deriving stock (Show, Eq, Generic)   deriving (FromJSON, ToJSON)-  via CustomJSON '[FieldLabelModifier '[StripPrefix "_assetDetails", CamelToSnake]] AssetDetails+  via CustomJSON '[ FieldLabelModifier+                    '[ StripPrefix "_assetDetails"+                     , CamelToSnake+                     , Rename "onchain_metadata_value" "onchain_metadata"+                     ]+                  ] AssetDetails +parseStandardMetadata :: Maybe Value -> Maybe AssetOnChainMetadata+parseStandardMetadata mbValue = mbValue >>= parseMaybe parseJSON++parseStandardMetadataInDetails :: AssetDetails -> AssetDetails+parseStandardMetadataInDetails+  details@AssetDetails{_assetDetailsOnchainMetadataValue = mbValue} =+  details { _assetDetailsOnchainStandardMetadata = parseStandardMetadata mbValue}++ instance ToSample AssetDetails where   toSamples = pure $ singleSample     AssetDetails@@ -113,11 +177,30 @@       , _assetDetailsQuantity = 12000       , _assetDetailsInitialMintTxHash = "6804edf9712d2b619edb6ac86861fe93a730693183a262b165fcc1ba1bc99cad"       , _assetDetailsMintOrBurnCount = 1-      , _assetDetailsOnchainMetadata = pure $-          AssetOnChainMetadata-            { _assetOnChainMetadataName = "My NFT token"-            , _assetOnChainMetadataImage = "ipfs://ipfs/QmfKyJ4tuvHowwKQCbCHj4L5T3fSj8cjs7Aau8V7BWv226"-            }+      , _assetDetailsOnchainMetadataValue = Just $+          (+            Object+             (fromList+               [ ("id",Number 630.0)+               , ("image",String "ipfs://ipfs/QmfKyJ4tuvHowwKQCbCHj4L5T3fSj8cjs7Aau8V7BWv226")+               , ("mediaType",String "image/png")+               , ("name",String "My NFT token")+               , ("files", Array+                   ( V.singleton+                     (Object+                       (fromList+                         [ ("name", String "Detailed image")+                         , ("mediaType", String "image/png")+                         , ("src", String "ipfs://ipfs/QmfKyJ4tuvHowwKQCbCHj4L5T3fSj8cjs7Aau8V7BWv226")+                         ]+                       )+                     )+                   )+                 )+               ]+             )+          )+      , _assetDetailsOnchainStandardMetadata = pure sampleAssetOnChainMetadata       , _assetDetailsMetadata = pure $           AssetMetadata             { _assetMetadataName = "nutcoin"@@ -127,6 +210,7 @@             , _assetMetadataLogo =  pure "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"             , _assetMetadataDecimals = pure 6             }+      , _assetDetailsOnchainMetadataExtra = Just "9f01582430303030303030302d303030302d303030302d303030302d3030303030303030303132334d47616d65585f4578616d706c65020203454c6576656c413145506f7765724231304553706565644131ff"       }  -- | Action of the asset.
src/Blockfrost/Types/Cardano/Pools.hs view
@@ -1,7 +1,8 @@ -- | Cardano Pools reponses  module Blockfrost.Types.Cardano.Pools-  ( PoolEpoch (..)+  ( Pool (..)+  , PoolEpoch (..)   , PoolInfo (..)   , PoolHistory (..)   , PoolMetadata (..)@@ -18,6 +19,39 @@ import Servant.Docs (ToSample (..), samples, singleSample)  import Blockfrost.Types.Shared++-- | Extended pool info+data Pool = Pool+  { _poolPoolId      :: PoolId -- ^ Bech32 encoded pool ID+  , _poolHex         :: Text -- ^ Hexadecimal pool ID.+  , _poolActiveStake :: Lovelaces -- ^ Active delegated amount+  , _poolLiveStake   :: Lovelaces -- ^ Currently delegated amount+  }+  deriving stock (Show, Eq, Generic)+  deriving (FromJSON, ToJSON)+  via CustomJSON '[FieldLabelModifier '[StripPrefix "_pool", CamelToSnake]] Pool++instance ToSample Pool where+  toSamples = pure $ samples+    [ Pool+        { _poolPoolId = "pool19u64770wqp6s95gkajc8udheske5e6ljmpq33awxk326zjaza0q"+        , _poolHex = "2f355f79ee007502d116ecb07e36f985b34cebf2d84118f5c6b455a1"+        , _poolActiveStake = 1541200000+        , _poolLiveStake = 1541400000+        }+    , Pool+        { _poolPoolId = "pool1dvla4zq98hpvacv20snndupjrqhuc79zl6gjap565nku6et5zdx"+        , _poolHex = "6b3fda88053dc2cee18a7c2736f032182fcc78a2fe912e869aa4edcd"+        , _poolActiveStake = 22200000+        , _poolLiveStake = 48955550+        }+    , Pool+        { _poolPoolId = "pool1wvccajt4eugjtf3k0ja3exjqdj7t8egsujwhcw4tzj4rzsxzw5w"+        , _poolHex = "73318ec975cf1125a6367cbb1c9a406cbcb3e510e49d7c3aab14aa31"+        , _poolActiveStake = 9989541215+        , _poolLiveStake = 168445464878+        }+    ]  -- | Retirement epoch for pool data PoolEpoch = PoolEpoch
+ src/Blockfrost/Types/Cardano/Utils.hs view
@@ -0,0 +1,136 @@+{-# LANGUAGE RecordWildCards #-}+-- | Cardano Utils responses++module Blockfrost.Types.Cardano.Utils+  ( DerivedAddress (..)+  , TxEval (..)+  , TxEvalBudget (..)+  , TxEvalResult (..)+  , evalSample+  , resultSample+  , TxEvalInput (..)+  ) where++import Data.Aeson+  ( FromJSON (..)+  , ToJSON (..)+  , Value (Array)+  , object+  , withObject+  , (.:)+  , (.:?)+  , (.=)+  )++import Blockfrost.Types.Shared.CBOR (CBORString(..))+import Data.Text (Text)+import Deriving.Aeson+import Servant.Docs (ToSample (..), singleSample)+import qualified Data.Char++-- | Derived Shelley address+data DerivedAddress = DerivedAddress+  { _derivedAddressXpub    :: Text    -- ^ Hexadecimal xpub+  , _derivedAddressRole    :: Integer -- ^ Account role+  , _derivedAddressIndex   :: Integer -- ^ Address index+  , _derivedAddressAddress :: Text    -- ^ Derived address+  }+  deriving stock (Show, Eq, Generic)+  deriving (FromJSON, ToJSON)+  via CustomJSON '[FieldLabelModifier '[StripPrefix "_derivedAddress", CamelToSnake]] DerivedAddress++instance ToSample DerivedAddress where+  toSamples = pure $ singleSample+    DerivedAddress+      { _derivedAddressXpub    = "d507c8f866691bd96e131334c355188b1a1d0b2fa0ab11545075aab332d77d9eb19657ad13ee581b56b0f8d744d66ca356b93d42fe176b3de007d53e9c4c4e7a"+      , _derivedAddressRole    = 0+      , _derivedAddressIndex   = 0+      , _derivedAddressAddress = "addr1q90sqnljxky88s0jsnps48jd872p7znzwym0jpzqnax6qs5nfrlkaatu28n0qzmqh7f2cpksxhpc9jefx3wrl0a2wu8q5amen7"+      }++data TxEvalBudget = TxEvalBudget+  { _txEvalBudgetMemory :: Integer -- ^ Memory budget+  , _txEvalBudgetCPU    :: Integer -- ^ CPU budget+  }+  deriving stock (Show, Eq, Generic)+  deriving (FromJSON, ToJSON)+  via CustomJSON '[FieldLabelModifier '[StripPrefix "_txEvalBudget", CamelToSnake]] TxEvalBudget++instance ToSample TxEvalBudget where+  toSamples = pure $ singleSample+    TxEvalBudget+      { _txEvalBudgetMemory = 1700+      , _txEvalBudgetCPU    = 476468+      }++-- | Transaction evaluation result+data TxEvalResult = TxEvalResult+  { _txEvalResultValidator :: Text         -- ^ Redeemer pointer+  , _txEvalResultBudget    :: TxEvalBudget -- ^ Budget+  }+  deriving stock (Show, Eq, Generic)+  deriving (FromJSON, ToJSON)+  via CustomJSON '[FieldLabelModifier '[StripPrefix "_txEvalResult", CamelToSnake]] TxEvalResult++resultSample :: TxEvalResult+resultSample =+  TxEvalResult+    { _txEvalResultValidator = "spend:0"+    , _txEvalResultBudget =+        TxEvalBudget+          { _txEvalBudgetMemory = 1700+          , _txEvalBudgetCPU    = 476468+          }+    }++instance ToSample TxEvalResult where+  toSamples = pure $ singleSample resultSample++-- | Transaction evaluation result wrapper+newtype TxEval = TxEval { _txEvalResult :: [TxEvalResult] }+  deriving stock (Show, Eq, Generic)++instance ToJSON TxEval where+  toJSON TxEval{..} =+    object+      [ "jsonrpc" .= ("2.0" :: Text)+      , "method" .= ("evaluateTransaction" :: Text)+      , "result" .= toJSON _txEvalResult+      ]++instance FromJSON TxEval where+  parseJSON = withObject "txEval" $ \o -> do+    (mErr :: Maybe Value) <- o .:? "error"+    case mErr of+      Just err -> fail $ show err+      Nothing -> pure ()++    r <- o .: "result"+    TxEval <$> parseJSON r++evalSample :: TxEval+evalSample = TxEval (pure resultSample)++instance ToSample TxEval where+  toSamples = pure $ singleSample evalSample++data LowerLeading+instance StringModifier LowerLeading where+  getStringModifier "" = ""+  getStringModifier (c:xs) = Data.Char.toLower c : xs++-- | Transaction evaluation input for UTXO variant+data TxEvalInput = TxEvalInput+  { _txEvalInputCbor              :: CBORString  -- ^ CBOR encoded transaction+  , _txEvalInputAdditionalUtxoSet :: Value -- ^ Additional UTXO set as JSON @Value@+  }+  deriving stock (Show, Eq, Generic)+  deriving (FromJSON, ToJSON)+  via CustomJSON '[FieldLabelModifier '[StripPrefix "_txEvalInput", LowerLeading]] TxEvalInput++instance ToSample TxEvalInput where+  toSamples = pure $ singleSample+    TxEvalInput+      { _txEvalInputCbor              = CBORString "83a40081825820daa9"+      , _txEvalInputAdditionalUtxoSet = Array mempty+      }
src/Blockfrost/Types/Shared/Amount.hs view
@@ -1,6 +1,7 @@ -- | Amount sum type  {-# LANGUAGE NumericUnderscores #-}+{-# LANGUAGE RecordWildCards #-}  module Blockfrost.Types.Shared.Amount   where@@ -31,7 +32,9 @@  -- | SomeDiscrete values always use scale of 1 unitScale :: Money.Scale-unitScale = let (Just s) = Money.scaleFromRational 1 in s+unitScale = case Money.scaleFromRational 1 of+  Just s -> s+  Nothing -> error "Money.scaleFromRational impossible"  instance ToJSON Money.SomeDiscrete where   toJSON sd =@@ -77,3 +80,59 @@                           "6804edf9712d2b619edb6ac86861fe93a730693183a262b165fcc1ba1bc99cad"                           '(1,1))     ]++-- | Like @Amount@, extended with @decimals` and `has_nft_onchain_metadata`+data AmountExtended =+    AdaAmountExtended Lovelaces+  | AssetAmountExtended+    { assetAmountExtendedDecimals              :: Maybe Int+    , assetAmountExtendedHasNftOnchainMetadata :: Bool+    , assetAmountExtendedValue                 :: Money.SomeDiscrete+    }+  deriving (Eq, Show, Ord, Generic)++instance ToJSON AmountExtended where+  toJSON (AdaAmountExtended lovelaces) =+    object [ "unit" .= ("lovelace" :: String)+           , "quantity" .= toJSON lovelaces+           , "decimals" .= (6 :: Int)+           , "has_nft_onchain_metadata" .= False+           ]+  toJSON (AssetAmountExtended {..}) =+    object [ "unit" .= Money.someDiscreteCurrency assetAmountExtendedValue+           , "quantity" .= show (Money.someDiscreteAmount assetAmountExtendedValue)+           , "decimals" .= assetAmountExtendedDecimals+           , "has_nft_onchain_metadata" .= assetAmountExtendedHasNftOnchainMetadata+           ]++instance FromJSON AmountExtended where+  parseJSON x@(Object o) = do+    (u :: String) <- o .: "unit"+    v <- o .: "quantity"+    assetAmountExtendedDecimals+      <- o .: "decimals"+    assetAmountExtendedHasNftOnchainMetadata+      <- o .: "has_nft_onchain_metadata"+    case u of+      "lovelace" -> AdaAmountExtended <$> parseJSON v+      _          -> do+        assetAmountExtendedValue <- parseJSON x+        pure AssetAmountExtended{..}++  parseJSON other = fail $ "Amount expecting object, got" ++ show other++instance ToSample AmountExtended where+  toSamples = pure $ samples+    [ AdaAmountExtended 42000000+    , AssetAmountExtended+        { assetAmountExtendedDecimals              = Nothing+        , assetAmountExtendedHasNftOnchainMetadata = True+        , assetAmountExtendedValue =+            Money.toSomeDiscrete+            (12 :: Money.Discrete'+                      "b0d07d45fe9514f80213f4020e5a61241458be626841cde717cb38a76e7574636f696e"+                      '(1,1))+        }+    ]++
src/Blockfrost/Types/Shared/CBOR.hs view
@@ -3,16 +3,36 @@ module Blockfrost.Types.Shared.CBOR   where +import Data.Aeson (FromJSON (..), ToJSON (..), withText) import Data.ByteString.Lazy (ByteString) import Servant.API (Accept (..), MimeRender (..), MimeUnrender (..)) import Servant.Docs (ToSample (..), singleSample) +import qualified Data.ByteString.Char8+import qualified Data.ByteString.Lazy+import qualified Data.Text+ data CBOR  -- | Wrapper for CBOR encoded `ByteString`s -- used for submitting a transaction newtype CBORString = CBORString ByteString   deriving stock (Eq, Show)++instance ToJSON CBORString where+  toJSON (CBORString bs) =+    toJSON+      . Data.Text.pack+      $ Data.ByteString.Char8.unpack+      $ Data.ByteString.Lazy.toStrict bs++instance FromJSON CBORString where+  parseJSON = withText "CBORString" $ \t ->+    pure+      $ CBORString+      <$> Data.ByteString.Lazy.fromStrict+        . Data.ByteString.Char8.pack+        $ Data.Text.unpack t  instance Accept CBOR where   contentType = pure "application/cbor"
src/Blockfrost/Util/LensRules.hs view
@@ -17,7 +17,7 @@     modNamer namer dname fnames fname =       map fixDefName (namer (fixTypeName dname) fnames fname) -    fixDefName (MethodName cname mname)=MethodName cname (fixName mname)+    fixDefName (MethodName cname mname) = MethodName cname (fixName mname)     fixDefName (TopName name)           = TopName (fixName name)      fixTypeName = mkName . fixTypeName' . nameBase
test/Cardano/Accounts.hs view
@@ -57,6 +57,11 @@     `shouldBe`     Right accountAssociatedAddressesExpected +  it "parses account associated addresses total sample" $ do+    eitherDecode accountAssociatedAddressesTotalSample+    `shouldBe`+    Right accountAssociatedAddressesTotalExpected+ accountSample = [r| {     "stake_address": "stake1ux3g2c9dx2nhhehyrezyxpkstartcqmu9hk63qgfkccw5rqttygt7",@@ -300,3 +305,52 @@     [ AddressAssociated "addr1qx2kd28nq8ac5prwg32hhvudlwggpgfp8utlyqxu6wqgz62f79qsdmm5dsknt9ecr5w468r9ey0fxwkdrwh08ly3tu9sy0f4qd"     , AddressAssociated "addr1q8j55h253zcvl326sk5qdt2n8z7eghzspe0ekxgncr796s2f79qsdmm5dsknt9ecr5w468r9ey0fxwkdrwh08ly3tu9sjmd35m"     ]++accountAssociatedAddressesTotalSample = [r|+{+  "stake_address": "stake1u9l5q5jwgelgagzyt6nuaasefgmn8pd25c8e9qpeprq0tdcp0e3uk",+  "received_sum": [+    {+      "unit": "lovelace",+      "quantity": "42000000"+    },+    {+      "unit": "b0d07d45fe9514f80213f4020e5a61241458be626841cde717cb38a76e7574636f696e",+      "quantity": "12"+    }+  ],+  "sent_sum": [+    {+      "unit": "lovelace",+      "quantity": "42000000"+    },+    {+      "unit": "b0d07d45fe9514f80213f4020e5a61241458be626841cde717cb38a76e7574636f696e",+      "quantity": "12"+    }+  ],+  "tx_count": 12+}+|]++accountAssociatedAddressesTotalExpected =+  AddressAssociatedTotal+    { _addressAssociatedTotalStakeAddress = "stake1u9l5q5jwgelgagzyt6nuaasefgmn8pd25c8e9qpeprq0tdcp0e3uk"+    , _addressAssociatedTotalReceivedSum =+        [ AdaAmount 42000000+        , AssetAmount+            $ Money.mkSomeDiscrete+                "b0d07d45fe9514f80213f4020e5a61241458be626841cde717cb38a76e7574636f696e"+                 unitScale+                 12+        ]+    , _addressAssociatedTotalSentSum =+        [ AdaAmount 42000000+        , AssetAmount+            $ Money.mkSomeDiscrete+                "b0d07d45fe9514f80213f4020e5a61241458be626841cde717cb38a76e7574636f696e"+                 unitScale+                 12+        ]+    , _addressAssociatedTotalTxCount = 12+    }
test/Cardano/Addresses.hs view
@@ -22,6 +22,11 @@     `shouldBe`     Right addressInfoExpected +  it "parses address info extended sample" $ do+    eitherDecode addressInfoExtendedSample+    `shouldBe`+    Right addressInfoExtendedExpected+   it "parses address info sample" $ do     eitherDecode addressInfoSample     `shouldBe`@@ -76,6 +81,49 @@     , _addressInfoType = Shelley     , _addressInfoScript = False     }++addressInfoExtendedSample = [r|+{+  "address": "addr1qxqs59lphg8g6qndelq8xwqn60ag3aeyfcp33c2kdp46a09re5df3pzwwmyq946axfcejy5n4x0y99wqpgtp2gd0k09qsgy6pz",+  "amount": [+    {+      "unit": "lovelace",+      "quantity": "42000000",+      "decimals": 6,+      "has_nft_onchain_metadata": false+    },+    {+      "unit": "b0d07d45fe9514f80213f4020e5a61241458be626841cde717cb38a76e7574636f696e",+      "quantity": "12",+      "decimals": null,+      "has_nft_onchain_metadata": true+    }+  ],+  "stake_address": "stake1ux3g2c9dx2nhhehyrezyxpkstartcqmu9hk63qgfkccw5rqttygt7",+  "type": "shelley",+  "script": false+}+|]++addressInfoExtendedExpected =+   AddressInfoExtended+      { _addressInfoExtendedAddress = "addr1qxqs59lphg8g6qndelq8xwqn60ag3aeyfcp33c2kdp46a09re5df3pzwwmyq946axfcejy5n4x0y99wqpgtp2gd0k09qsgy6pz"+      , _addressInfoExtendedAmount =+        [ AdaAmountExtended 42000000+        , AssetAmountExtended+            { assetAmountExtendedDecimals              = Nothing+            , assetAmountExtendedHasNftOnchainMetadata = True+            , assetAmountExtendedValue =+                Money.mkSomeDiscrete+                  "b0d07d45fe9514f80213f4020e5a61241458be626841cde717cb38a76e7574636f696e"+                  unitScale+                  12+            }+        ]+      , _addressInfoExtendedStakeAddress = pure "stake1ux3g2c9dx2nhhehyrezyxpkstartcqmu9hk63qgfkccw5rqttygt7"+      , _addressInfoExtendedType = Shelley+      , _addressInfoExtendedScript = False+      }  addressDetailsSample = [r| {
test/Cardano/Assets.hs view
@@ -6,7 +6,9 @@ module Cardano.Assets   where -import Data.Aeson (decode, eitherDecode, encode)+import Data.Aeson (Value (..), decode, eitherDecode, encode)+import Data.Aeson.KeyMap (fromList)+import qualified Data.Vector as V (singleton) import Data.Text (Text) import qualified Money import Test.Hspec@@ -23,7 +25,7 @@     Right assetInfoExpected    it "parses assets details sample" $ do-    eitherDecode assetDetailsSample+    (parseStandardMetadataInDetails <$> eitherDecode assetDetailsSample)     `shouldBe`     Right assetDetailsExpected @@ -85,8 +87,19 @@   "initial_mint_tx_hash": "6804edf9712d2b619edb6ac86861fe93a730693183a262b165fcc1ba1bc99cad",   "mint_or_burn_count": 1,   "onchain_metadata": {+    "id": 630.0,     "name": "My NFT token",-    "image": "ipfs://ipfs/QmfKyJ4tuvHowwKQCbCHj4L5T3fSj8cjs7Aau8V7BWv226"+    "description": "A cool token for joy and fun.",+    "image": "ipfs://ipfs/QmfKyJ4tuvHowwKQCbCHj4L5T3fSj8cjs7Aau8V7BWv226",+    "mediaType": "image/png",+    "files" :+      [+        {+          "mediaType": "image/png",+          "name": "Detailed image",+          "src": "ipfs://ipfs/QmfKyJ4tuvHowwKQCbCHj4L5T3fSj8cjs7Aau8V7BWv226"+        }+      ]   },   "metadata": {     "name": "nutcoin",@@ -95,7 +108,8 @@     "url": "https://www.stakenuts.com/",     "logo": "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",     "decimals": 6-  }+  },+  "onchain_metadata_extra": "9f01582430303030303030302d303030302d303030302d303030302d3030303030303030303132334d47616d65585f4578616d706c65020203454c6576656c413145506f7765724231304553706565644131ff" } |] @@ -108,11 +122,45 @@     , _assetDetailsQuantity = 12000     , _assetDetailsInitialMintTxHash = "6804edf9712d2b619edb6ac86861fe93a730693183a262b165fcc1ba1bc99cad"     , _assetDetailsMintOrBurnCount = 1-    , _assetDetailsOnchainMetadata = pure $+    , _assetDetailsOnchainMetadataValue = Just $+        (+          Object+            (fromList+              [ ("id",Number 630.0)+              , ("image",String "ipfs://ipfs/QmfKyJ4tuvHowwKQCbCHj4L5T3fSj8cjs7Aau8V7BWv226")+              , ("mediaType",String "image/png")+              , ("name",String "My NFT token")+              , ("description",String "A cool token for joy and fun.")+              , ("files", Array+                  ( V.singleton+                    (Object+                      (fromList+                        [ ("name", String "Detailed image")+                        , ("mediaType", String "image/png")+                        , ("src", String "ipfs://ipfs/QmfKyJ4tuvHowwKQCbCHj4L5T3fSj8cjs7Aau8V7BWv226")+                        ]+                      )+                    )+                  )+                )+              ]+            )+        )+    , _assetDetailsOnchainStandardMetadata = pure $         AssetOnChainMetadata-          { _assetOnChainMetadataName = "My NFT token"-          , _assetOnChainMetadataImage = "ipfs://ipfs/QmfKyJ4tuvHowwKQCbCHj4L5T3fSj8cjs7Aau8V7BWv226"-          }+              { _assetOnChainMetadataName = Just "My NFT token"+              , _assetOnChainMetadataDescription = Just "A cool token for joy and fun."+              , _assetOnChainMetadataImage = Just "ipfs://ipfs/QmfKyJ4tuvHowwKQCbCHj4L5T3fSj8cjs7Aau8V7BWv226"+              , _assetOnChainMetadataMediaType = Just "image/png"+              , _assetOnChainMetadataFiles = Just+                [+                  MetadataMediaFile+                    { _metadataMediaFileName = Just "Detailed image"+                    , _metadataMediaFileMediaType = Just "image/png"+                    , _metadataMediaFileSrc = Just "ipfs://ipfs/QmfKyJ4tuvHowwKQCbCHj4L5T3fSj8cjs7Aau8V7BWv226"+                    }+                ]+              }     , _assetDetailsMetadata = pure $         AssetMetadata           { _assetMetadataName = "nutcoin"@@ -122,6 +170,7 @@           , _assetMetadataLogo =  pure "iVBORw0KGgoAAAANSUhEUgAAADAAAAAoCAYAAAC4h3lxAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QA/wD/AP+gvaeTAAAAB3RJTUUH5QITCDUPjqwFHwAAB9xJREFUWMPVWXtsU9cZ/8499/r6dZ3E9rUdO7ZDEgglFWO8KaOsJW0pCLRKrN1AqqYVkqoqrYo0ja7bpElru1WairStFKY9WzaE1E1tx+jokKqwtqFNyhKahEJJyJNgJ37E9r1+3HvO/sFR4vhx7SBtfH/F3/l93/f7ne/4PBxEKYU72dj/ZfH772v1TU+HtqbTaX8wOO01GPQpRVH7JEm+vGHDuq6z7/8jUSoHKtaBKkEUFUXdajDy1hUrmrs6zn/wWS7m7pZVjMUirKGUTnzc+e9xLcTrPPVfZzDz06Sc2lyQGEIyAPzT7Xa+dvE/3e+XLaCxoflHsVj8MAAYs74aa/WHoenwvpkZKeFy2Z5NJlOPUkqXZccFwSSrKjlyffjLH+TL6XTUGTGL/6hklD3ldIrj2M5MRmkLBMcvaRLQ1Nj88sxM/HCBfMP+eu/OYGDqe6l0WmpoqJ/88upgrU7HrQNA/cFg6MlkKiLlBtVUO40cx54BgHvLIT/HJLvdeqh/4NKxogKWN7fsCoUi7xTLxLJ4vLq6ak//wKVOrdXtttrTDMPsqJA8AAAwDErdu3VL3alTf5ma9eWCpoKhn5dKpCiqJxicPucQPVu0FHaInn35yHMcKwPAa4SQ3QCwFgDWUko3qSr5vqqSgTypuEg4Mo/zvA74/Y0rZSnZU8akSHV17k2fXfy0txjI5224kEym1s/1EUI7LBbztweHrkzkizn49LP6U6feepFSeggAQK/n04SQZ8bGrxdeQjZrbRvGzLH5hcibRqOhPplMfS1fIY5jz4xPDBdcGggho2h3z9sOLRazdG3wqp9SMgUlzGZ17SSEPsRx7J8CwfGu3PF57WhqqjfN/VxVJUxKUrIdITAXKpDJKFscosdfaFy0u+/K9aXTmXe0kAcAmA5Nng5Hbj6Tj/wCAYFAcN7uEY3GXGazMSHLqVVFapgBoMPna9yqhRAAgCTJMa3YUjZPgNFkSlWYx5eUkx+0tKx83V3rF+cVYJjruWCe133DIXqMmrNrFSDabRcWkywYmG5XFOW6aHcfb9324CoAgMmbo9MIoXkneCajiAihV/c/8eSiBSw4BxyiZxQA6m7H7FBKT2CMn2MY5jFFUX6ZO+5w2j8aHZ7YH40FByrJD5DnHGAY5uTtIA8AgBDaR4F2Yxb3WizCgmtA4ObUPSazodduqz3Suu0hf0U1cjvgdNSJ1dWWveFwdDUAtAiC2Uopdcdi8c9Zlh3GmDGl05mtAKAvo47EcdwThJCjqqpWFxALlNITomg73tff21GRAJez7iVK4WGGYfoJIQduBsbm7UrLm1ueCoUiv65kpiilw1ZbzcFoZOYoIcRTAn6eYZgXJm+Oni+Vd3YJbdyweSch9HlK6SpVVfcyDDq7Yf3m2XPBIXraKyV/a4b9UkLawbLsZgB4rwR8CyGkw13r+5fX27BckwBAEJ47oKpk8+DgUIdod7fV1vqOAMDrlZLPmqKoB+rrvXIgOP6w0WjYy3Ls5RL4bUk52bVm9fqnCk7M3CXU2ND8+MxM7BcIIftiyRYyntcdHh0bmr0wfmXl6p2SJB2KRmP3l4j7zejYUFtRAQAAgslm1Bv4nyGEDpYiIwjmjw0G/RjP866JiclNqqqWfKLq9fyZkdHBBXcnl9O71GDgD8bj0ncRQqZ8sRgzL9yYHH2pqICsOUTPLgA4CXNeZFmzWIS/YhYfjUZmvqPjuceSckrz25pS2h2cmlhbaBwhzr6kfsnL8Xhif55YYFl23Y3Jkdl7EVMoUSA4/q6qqNsBIPd11e52u45FwtG3CSH7yiEPAGC1Vt9dXGBmanDoygFLlbAjtzZCCMyC6VeaOpA1l9N7l1kwtauKaozHE28YTQaQpeR7+TqjxXheR0fHhhgt2CX1S3clEtKC16HL5djYe+niBU0CcmYA2W21/Qih5ZqDcoxlMZ24MaJJAABA87IVJ8Lh6N65Pr1B/+LIyLUfAhRZQvnM6ah7ZDHkAQB0vK6/HHxNTc2ruT5Zkldn/y5LACFk+2LIAwAwCGl6yGSt88KHXbmrBCHkqEgAz+vWLFZALJb4qNwYhFDhCSknkSwnQ4sVgDFeWg7+gQe2r1tAmkGTFQlACHWVg89nhJA9ot3dphV/eeCLp/Pw6K5IQP0S39uLFXCLwDG7zf1cKZxD9LSlUunHc/12u/2t2Vzl/rzu8zb8PZlM7bwdQgDgPK/nX2nddt+53//ht3LW2dS0fF0iLj2vquojuQFmwXRucPBKa8UCmpe1iOFwpAsAfLdJBFBKwVIlXJ2JxqKCxbwyHkvoCkAlv9/71U+7Oq+UJWDZ0hViJBL1cRynbNq0sSeeiPl6ei4NqIqq6TSmlB7X6bjuTEY5pgWfzwxGPZhMpt39/b3vzvWXFGCzulZjjM/DrauDwcAr8bjcgzGjZUuVBMH8k2uDX7wCAFDr8n2LEPI7SqmhTP6SzVbz6MDlz0/nDpT8EmOM22HOvUeWU2wp8iyLgRL6hk7Hrc2SBwC4MTlykmXZRozxn00mbVcphNA5jJmV+chr6oDd5l6jN/A/TqfSuwEAGITGMIsvGo3GTwTB3Dc2NjGSxdZYq4VIOOoNBANnKE0XPXE3brjHOTQ08k2MmVZOxzVJCbkFIQSCYEphzPaFQuGzTpfjb319PZ8UFXin/5OvrHPg/9HueAH/BSUqOuNZm4fyAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIxLTAyLTE5VDA4OjUyOjI1KzAwOjAwCmFGlgAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMS0wMi0xOVQwODo1MjoyMyswMDowMBjsyxAAAAAASUVORK5CYII="           , _assetMetadataDecimals = pure 6           }+    , _assetDetailsOnchainMetadataExtra = Just "9f01582430303030303030302d303030302d303030302d303030302d3030303030303030303132334d47616d65585f4578616d706c65020203454c6576656c413145506f7765724231304553706565644131ff"     }  assetHistorySample = [r|
test/Cardano/Pools.hs view
@@ -17,6 +17,11 @@  spec_pools :: Spec spec_pools = do+  it "parses pools sample" $ do+    eitherDecode poolsSample+    `shouldBe`+    Right poolsExpected+   it "parses pool epoch sample" $ do     eitherDecode poolEpochSample     `shouldBe`@@ -56,6 +61,51 @@     eitherDecode poolUpdatesSample     `shouldBe`     Right poolUpdatesExpected++poolsSample = [r|+[+  {+    "pool_id": "pool19u64770wqp6s95gkajc8udheske5e6ljmpq33awxk326zjaza0q",+    "hex": "2f355f79ee007502d116ecb07e36f985b34cebf2d84118f5c6b455a1",+    "active_stake": "1541200000",+    "live_stake": "1541400000"+  },+  {+    "pool_id": "pool1dvla4zq98hpvacv20snndupjrqhuc79zl6gjap565nku6et5zdx",+    "hex": "6b3fda88053dc2cee18a7c2736f032182fcc78a2fe912e869aa4edcd",+    "active_stake": "22200000",+    "live_stake": "48955550"+  },+  {+    "pool_id": "pool1wvccajt4eugjtf3k0ja3exjqdj7t8egsujwhcw4tzj4rzsxzw5w",+    "hex": "73318ec975cf1125a6367cbb1c9a406cbcb3e510e49d7c3aab14aa31",+    "active_stake": "9989541215",+    "live_stake": "168445464878"+  }+]+|]++poolsExpected =+  [ Pool+      { _poolPoolId = "pool19u64770wqp6s95gkajc8udheske5e6ljmpq33awxk326zjaza0q"+      , _poolHex = "2f355f79ee007502d116ecb07e36f985b34cebf2d84118f5c6b455a1"+      , _poolActiveStake = 1541200000+      , _poolLiveStake = 1541400000+      }+  , Pool+      { _poolPoolId = "pool1dvla4zq98hpvacv20snndupjrqhuc79zl6gjap565nku6et5zdx"+      , _poolHex = "6b3fda88053dc2cee18a7c2736f032182fcc78a2fe912e869aa4edcd"+      , _poolActiveStake = 22200000+      , _poolLiveStake = 48955550+      }+  , Pool+      { _poolPoolId = "pool1wvccajt4eugjtf3k0ja3exjqdj7t8egsujwhcw4tzj4rzsxzw5w"+      , _poolHex = "73318ec975cf1125a6367cbb1c9a406cbcb3e510e49d7c3aab14aa31"+      , _poolActiveStake = 9989541215+      , _poolLiveStake = 168445464878+      }+  ]+  poolEpochSample = [r| [
+ test/Cardano/Utils.hs view
@@ -0,0 +1,179 @@+{-# LANGUAGE NumericUnderscores #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TemplateHaskell #-}++module Cardano.Utils+  where++import Data.Aeson (decode, eitherDecode, encode, object, (.=), Value (Array))+import qualified Data.Either+import Data.Text (Text)+import qualified Money+import Test.Hspec+import Test.Tasty.Hspec+import Text.RawString.QQ++import Blockfrost.Types++spec_scripts :: Spec+spec_scripts = do+  it "parses derived address sample" $ do+    eitherDecode derivedAddressSample+    `shouldBe`+    Right derivedAddressExpected++  it "parses tx eval sample" $ do+    eitherDecode txEvalSample+    `shouldBe`+    Right txEvalExpected++  it "fails to parse tx eval error" $ do+    eitherDecode txEvalErrorSample+    `shouldSatisfy`+    (Data.Either.isLeft :: Either String TxEval -> Bool)++  it "parses tx eval input sample" $ do+    eitherDecode txEvalInputSample+    `shouldBe`+    Right txEvalInputExpected++derivedAddressSample = [r|+{+  "xpub": "d507c8f866691bd96e131334c355188b1a1d0b2fa0ab11545075aab332d77d9eb19657ad13ee581b56b0f8d744d66ca356b93d42fe176b3de007d53e9c4c4e7a",+  "role": 0,+  "index": 0,+  "address": "addr1q90sqnljxky88s0jsnps48jd872p7znzwym0jpzqnax6qs5nfrlkaatu28n0qzmqh7f2cpksxhpc9jefx3wrl0a2wu8q5amen7"+}+|]++derivedAddressExpected =+  DerivedAddress+    { _derivedAddressXpub    = "d507c8f866691bd96e131334c355188b1a1d0b2fa0ab11545075aab332d77d9eb19657ad13ee581b56b0f8d744d66ca356b93d42fe176b3de007d53e9c4c4e7a"+    , _derivedAddressRole    = 0+    , _derivedAddressIndex   = 0+    , _derivedAddressAddress = "addr1q90sqnljxky88s0jsnps48jd872p7znzwym0jpzqnax6qs5nfrlkaatu28n0qzmqh7f2cpksxhpc9jefx3wrl0a2wu8q5amen7"+    }++txEvalSample = [r|+{+  "jsonrpc": "2.0",+  "method": "evaluateTransaction",+  "result": [{+    "validator": "spend:0",+    "budget": {+      "memory": 1700,+      "cpu": 476468+    }+  }]+}+|]++txEvalExpected = evalSample++-- Stolen from+-- https://github.com/CardanoSolutions/ogmios/blob/master/server/test/vectors/EvaluateTransactionResponse/000.json+-- Mozilla Public License 2.0+txEvalErrorSample = [r|+{+  "jsonrpc": "2.0",+  "method": "evaluateTransaction",+  "error": {+    "code": 3010,+    "message": "Some scripts of the transactions terminated with error(s).",+    "data": [+      {+        "validator": "spend:4",+        "error": {+          "code": 3011,+          "message": "An associated script witness is missing. Indeed, any script used in a transaction (when spending, minting, withdrawing or publishing certificates) must be provided in full with the transaction. Scripts must therefore be added either to the witness set or provided as a reference inputs should you use Plutus V2+ and a format from Babbage and beyond.",+          "data": {+            "missingScripts": [+              "certificate:3"+            ]+          }+        }+      },+      {+        "validator": "mint:0",+        "error": {+          "code": 3011,+          "message": "An associated script witness is missing. Indeed, any script used in a transaction (when spending, minting, withdrawing or publishing certificates) must be provided in full with the transaction. Scripts must therefore be added either to the witness set or provided as a reference inputs should you use Plutus V2+ and a format from Babbage and beyond.",+          "data": {+            "missingScripts": [+              "certificate:11"+            ]+          }+        }+      },+      {+        "validator": "mint:3",+        "error": {+          "code": 3011,+          "message": "An associated script witness is missing. Indeed, any script used in a transaction (when spending, minting, withdrawing or publishing certificates) must be provided in full with the transaction. Scripts must therefore be added either to the witness set or provided as a reference inputs should you use Plutus V2+ and a format from Babbage and beyond.",+          "data": {+            "missingScripts": [+              "withdrawal:7"+            ]+          }+        }+      },+      {+        "validator": "mint:7",+        "error": {+          "code": 3011,+          "message": "An associated script witness is missing. Indeed, any script used in a transaction (when spending, minting, withdrawing or publishing certificates) must be provided in full with the transaction. Scripts must therefore be added either to the witness set or provided as a reference inputs should you use Plutus V2+ and a format from Babbage and beyond.",+          "data": {+            "missingScripts": [+              "mint:4"+            ]+          }+        }+      },+      {+        "validator": "mint:11",+        "error": {+          "code": 3117,+          "message": "The transaction contains unknown UTxO references as inputs. This can happen if the inputs you're trying to spend have already been spent, or if you've simply referred to non-existing UTxO altogether. The field 'data.unknownOutputReferences' indicates all unknown inputs.",+          "data": {+            "unknownOutputReferences": [+              {+                "transaction": {+                  "id": "a10897006ca78f6ce87fc6e2b139d92a896de01d62fe01f4fd0eccc6a10075c1"+                },+                "index": 14+              }+            ]+          }+        }+      },+      {+        "validator": "certificate:2",+        "error": {+          "code": 3011,+          "message": "An associated script witness is missing. Indeed, any script used in a transaction (when spending, minting, withdrawing or publishing certificates) must be provided in full with the transaction. Scripts must therefore be added either to the witness set or provided as a reference inputs should you use Plutus V2+ and a format from Babbage and beyond.",+          "data": {+            "missingScripts": [+              "withdrawal:2"+            ]+          }+        }+      }+    ]+  },+  "id": null+}+|]++txEvalInputSample = [r|+{+  "cbor": "sample",+  "additionalUtxoSet": []+}+|]++txEvalInputExpected =+  TxEvalInput+    { _txEvalInputCbor              = CBORString "sample"+    , _txEvalInputAdditionalUtxoSet = Array mempty+    }