From d8ac20f3bc3432927a1bebdca7e741d864e477eb Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Tue, 27 Jun 2023 19:28:01 +0530 Subject: [PATCH 01/24] Feat 28: GHC v9.2.8 support --- maestro-exe/Maestro/Run/General.hs | 9 +++++++++ maestro-exe/Main.hs | 2 ++ maestro-sdk.cabal | 8 +++++--- 3 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 maestro-exe/Maestro/Run/General.hs diff --git a/maestro-exe/Maestro/Run/General.hs b/maestro-exe/Maestro/Run/General.hs new file mode 100644 index 0000000..40c55be --- /dev/null +++ b/maestro-exe/Maestro/Run/General.hs @@ -0,0 +1,9 @@ +module Maestro.Run.General where + +import Maestro.Client +import Text.Printf (printf) + +runGeneralAPI :: MaestroEnv -> IO () +runGeneralAPI mEnv = do + chainTip <- getChainTip mEnv + printf "Querying chain-tip, received: топ\n%s\n" (show chainTip) diff --git a/maestro-exe/Main.hs b/maestro-exe/Main.hs index 37d0d33..bda3c30 100644 --- a/maestro-exe/Main.hs +++ b/maestro-exe/Main.hs @@ -4,6 +4,7 @@ import qualified Data.Text as T import Maestro.Client.Env import Maestro.Run.Datum import Maestro.Run.Epochs +import Maestro.Run.General import Maestro.Run.Pools import Maestro.Run.Scripts import Maestro.Run.Tx @@ -20,6 +21,7 @@ main = do runEpochsAPI env runDatumAPI env runScriptsAPI env + runGeneralAPI env where maestroKey = getEnv "MAESTRO_API_KEY" diff --git a/maestro-sdk.cabal b/maestro-sdk.cabal index 682c993..97acfe8 100644 --- a/maestro-sdk.cabal +++ b/maestro-sdk.cabal @@ -12,6 +12,7 @@ build-type: Simple category: Blockchain, Cardano, SDK, API, REST extra-doc-files: CHANGELOG.md extra-source-files: README.md +tested-with: GHC == 8.10.7, GHC == 9.2.8 source-repository head type: git @@ -78,7 +79,7 @@ library -- other-modules: -- other-extensions: build-depends: - , base ^>=4.14.3.0 + , base >= 4.14.3.0 && < 4.19 , bytestring , aeson , containers @@ -111,7 +112,7 @@ test-suite maestro-sdk-tests Maestro.Test.Transaction build-depends: - base ^>=4.14.3.0 + base , maestro-sdk , aeson , bytestring @@ -129,6 +130,7 @@ executable maestro-exe default-language: Haskell2010 other-modules: Maestro.Run.Datum + Maestro.Run.General Maestro.Run.Pools Maestro.Run.Scripts Maestro.Run.Tx @@ -137,6 +139,6 @@ executable maestro-exe hs-source-dirs: maestro-exe main-is: Main.hs build-depends: - base ^>=4.14.3.0, + base, maestro-sdk, text From 795c39d943e93ae8cc346f5ef3bd32c701f1c156 Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Wed, 5 Jul 2023 14:52:05 +0530 Subject: [PATCH 02/24] Feat 30: Isolating earlier version so as to support multiple versions simultaneously --- maestro-exe/Maestro/Run/Datum.hs | 2 +- maestro-exe/Maestro/Run/Epochs.hs | 2 +- maestro-exe/Maestro/Run/General.hs | 2 +- maestro-exe/Maestro/Run/Pools.hs | 4 +- maestro-exe/Maestro/Run/Scripts.hs | 4 +- maestro-exe/Maestro/Run/Tx.hs | 4 +- maestro-exe/Main.hs | 4 +- maestro-sdk.cabal | 62 +++++++++++----------- src/Maestro/{API.hs => API/V0.hs} | 24 ++++----- src/Maestro/API/{ => V0}/Accounts.hs | 5 +- src/Maestro/API/{ => V0}/Address.hs | 7 ++- src/Maestro/API/{ => V0}/Assets.hs | 5 +- src/Maestro/API/{ => V0}/Datum.hs | 4 +- src/Maestro/API/{ => V0}/Epochs.hs | 5 +- src/Maestro/API/{ => V0}/General.hs | 4 +- src/Maestro/API/{ => V0}/Pool.hs | 4 +- src/Maestro/API/{ => V0}/Scripts.hs | 6 +-- src/Maestro/API/{ => V0}/Transaction.hs | 8 +-- src/Maestro/API/{ => V0}/TxManager.hs | 8 +-- src/Maestro/Client.hs | 29 ---------- src/Maestro/Client/Core.hs | 4 +- src/Maestro/Client/Env.hs | 22 +++++--- src/Maestro/Client/V0.hs | 29 ++++++++++ src/Maestro/Client/{ => V0}/Accounts.hs | 10 ++-- src/Maestro/Client/{ => V0}/Address.hs | 11 ++-- src/Maestro/Client/{ => V0}/Assets.hs | 11 ++-- src/Maestro/Client/{ => V0}/Datum.hs | 10 ++-- src/Maestro/Client/{ => V0}/Epochs.hs | 8 +-- src/Maestro/Client/{ => V0}/General.hs | 8 +-- src/Maestro/Client/{ => V0}/Pools.hs | 9 ++-- src/Maestro/Client/{ => V0}/Scripts.hs | 10 ++-- src/Maestro/Client/{ => V0}/Transaction.hs | 12 ++--- src/Maestro/Client/{ => V0}/TxManager.hs | 10 ++-- src/Maestro/Types.hs | 21 -------- src/Maestro/Types/V0.hs | 21 ++++++++ src/Maestro/Types/{ => V0}/Accounts.hs | 7 ++- src/Maestro/Types/{ => V0}/Address.hs | 2 +- src/Maestro/Types/{ => V0}/Assets.hs | 12 ++--- src/Maestro/Types/{ => V0}/Common.hs | 8 ++- src/Maestro/Types/{ => V0}/Datum.hs | 8 +-- src/Maestro/Types/{ => V0}/Epochs.hs | 18 +++---- src/Maestro/Types/{ => V0}/General.hs | 34 +++++------- src/Maestro/Types/{ => V0}/Pool.hs | 10 ++-- src/Maestro/Types/Version.hs | 6 +++ test/Maestro/Test/Datum.hs | 2 +- test/Maestro/Test/Epochs.hs | 2 +- test/Maestro/Test/General.hs | 2 +- test/Maestro/Test/Pool.hs | 2 +- test/Maestro/Test/Transaction.hs | 2 +- 49 files changed, 254 insertions(+), 250 deletions(-) rename src/Maestro/{API.hs => API/V0.hs} (65%) rename src/Maestro/API/{ => V0}/Accounts.hs (90%) rename src/Maestro/API/{ => V0}/Address.hs (84%) rename src/Maestro/API/{ => V0}/Assets.hs (93%) rename src/Maestro/API/{ => V0}/Datum.hs (80%) rename src/Maestro/API/{ => V0}/Epochs.hs (75%) rename src/Maestro/API/{ => V0}/General.hs (87%) rename src/Maestro/API/{ => V0}/Pool.hs (96%) rename src/Maestro/API/{ => V0}/Scripts.hs (65%) rename src/Maestro/API/{ => V0}/Transaction.hs (85%) rename src/Maestro/API/{ => V0}/TxManager.hs (62%) delete mode 100644 src/Maestro/Client.hs create mode 100644 src/Maestro/Client/V0.hs rename src/Maestro/Client/{ => V0}/Accounts.hs (83%) rename src/Maestro/Client/{ => V0}/Address.hs (87%) rename src/Maestro/Client/{ => V0}/Assets.hs (93%) rename src/Maestro/Client/{ => V0}/Datum.hs (68%) rename src/Maestro/Client/{ => V0}/Epochs.hs (79%) rename src/Maestro/Client/{ => V0}/General.hs (85%) rename src/Maestro/Client/{ => V0}/Pools.hs (91%) rename src/Maestro/Client/{ => V0}/Scripts.hs (68%) rename src/Maestro/Client/{ => V0}/Transaction.hs (86%) rename src/Maestro/Client/{ => V0}/TxManager.hs (72%) delete mode 100644 src/Maestro/Types.hs create mode 100644 src/Maestro/Types/V0.hs rename src/Maestro/Types/{ => V0}/Accounts.hs (92%) rename src/Maestro/Types/{ => V0}/Address.hs (93%) rename src/Maestro/Types/{ => V0}/Assets.hs (90%) rename src/Maestro/Types/{ => V0}/Common.hs (96%) rename src/Maestro/Types/{ => V0}/Datum.hs (74%) rename src/Maestro/Types/{ => V0}/Epochs.hs (79%) rename src/Maestro/Types/{ => V0}/General.hs (91%) rename src/Maestro/Types/{ => V0}/Pool.hs (97%) create mode 100644 src/Maestro/Types/Version.hs diff --git a/maestro-exe/Maestro/Run/Datum.hs b/maestro-exe/Maestro/Run/Datum.hs index 5d7c855..e07134e 100644 --- a/maestro-exe/Maestro/Run/Datum.hs +++ b/maestro-exe/Maestro/Run/Datum.hs @@ -1,6 +1,6 @@ module Maestro.Run.Datum where -import Maestro.Client +import Maestro.Client.V0 import Text.Printf (printf) runDatumAPI :: MaestroEnv -> IO () diff --git a/maestro-exe/Maestro/Run/Epochs.hs b/maestro-exe/Maestro/Run/Epochs.hs index 2a08084..67a7d5b 100644 --- a/maestro-exe/Maestro/Run/Epochs.hs +++ b/maestro-exe/Maestro/Run/Epochs.hs @@ -1,6 +1,6 @@ module Maestro.Run.Epochs where -import Maestro.Client +import Maestro.Client.V0 runEpochsAPI :: MaestroEnv -> IO () runEpochsAPI mEnv = do diff --git a/maestro-exe/Maestro/Run/General.hs b/maestro-exe/Maestro/Run/General.hs index 40c55be..1d29e89 100644 --- a/maestro-exe/Maestro/Run/General.hs +++ b/maestro-exe/Maestro/Run/General.hs @@ -1,6 +1,6 @@ module Maestro.Run.General where -import Maestro.Client +import Maestro.Client.V0 import Text.Printf (printf) runGeneralAPI :: MaestroEnv -> IO () diff --git a/maestro-exe/Maestro/Run/Pools.hs b/maestro-exe/Maestro/Run/Pools.hs index d767b60..0bb8ae7 100644 --- a/maestro-exe/Maestro/Run/Pools.hs +++ b/maestro-exe/Maestro/Run/Pools.hs @@ -1,7 +1,7 @@ module Maestro.Run.Pools where -import Maestro.Client -import Maestro.Types +import Maestro.Client.V0 +import Maestro.Types.V0 poolId :: Bech32StringOf PoolId poolId = "pool1rkfs9glmfva3jd0q9vnlqvuhnrflpzj4l07u6sayfx5k7d788us" diff --git a/maestro-exe/Maestro/Run/Scripts.hs b/maestro-exe/Maestro/Run/Scripts.hs index ad64052..f51e30d 100644 --- a/maestro-exe/Maestro/Run/Scripts.hs +++ b/maestro-exe/Maestro/Run/Scripts.hs @@ -1,7 +1,7 @@ module Maestro.Run.Scripts where -import Maestro.Client -import Text.Printf (printf) +import Maestro.Client.V0 +import Text.Printf (printf) runScriptsAPI :: MaestroEnv -> IO () runScriptsAPI mEnv = do diff --git a/maestro-exe/Maestro/Run/Tx.hs b/maestro-exe/Maestro/Run/Tx.hs index 73acec3..963f1a7 100644 --- a/maestro-exe/Maestro/Run/Tx.hs +++ b/maestro-exe/Maestro/Run/Tx.hs @@ -1,7 +1,7 @@ module Maestro.Run.Tx where -import Maestro.Client -import Maestro.Types +import Maestro.Client.V0 +import Maestro.Types.V0 txHash :: HashStringOf Tx txHash = "7fdf7a20ba50d841344ab0cb368da6a047ce1e2a29b707586f61f0b8fea6bcf2" diff --git a/maestro-exe/Main.hs b/maestro-exe/Main.hs index bda3c30..dd927a3 100644 --- a/maestro-exe/Main.hs +++ b/maestro-exe/Main.hs @@ -1,7 +1,7 @@ module Main (main) where import qualified Data.Text as T -import Maestro.Client.Env +import Maestro.Client.V0 import Maestro.Run.Datum import Maestro.Run.Epochs import Maestro.Run.General @@ -15,7 +15,7 @@ main :: IO () main = do apiKey <- maestroKey - env <- mkMaestroEnv (T.pack apiKey) Preprod + env <- mkMaestroEnv (T.pack apiKey) Preprod V0 runPoolsAPI env runTxApi env runEpochsAPI env diff --git a/maestro-sdk.cabal b/maestro-sdk.cabal index 97acfe8..be93cce 100644 --- a/maestro-sdk.cabal +++ b/maestro-sdk.cabal @@ -39,42 +39,42 @@ common common library import: common exposed-modules: - Maestro.API - Maestro.API.Accounts - Maestro.API.Address - Maestro.API.Assets - Maestro.API.Datum - Maestro.API.Epochs - Maestro.API.General - Maestro.API.Pool - Maestro.API.Scripts - Maestro.API.Transaction - Maestro.API.TxManager + Maestro.API.V0 + Maestro.API.V0.Accounts + Maestro.API.V0.Address + Maestro.API.V0.Assets + Maestro.API.V0.Datum + Maestro.API.V0.Epochs + Maestro.API.V0.General + Maestro.API.V0.Pool + Maestro.API.V0.Scripts + Maestro.API.V0.Transaction + Maestro.API.V0.TxManager - Maestro.Client + Maestro.Client.V0 Maestro.Client.Core Maestro.Client.Core.Pagination - Maestro.Client.Datum + Maestro.Client.V0.Datum Maestro.Client.Env - Maestro.Client.Epochs - Maestro.Client.Accounts - Maestro.Client.Address - Maestro.Client.Assets - Maestro.Client.General - Maestro.Client.Pools - Maestro.Client.Scripts - Maestro.Client.Transaction - Maestro.Client.TxManager + Maestro.Client.V0.Epochs + Maestro.Client.V0.Accounts + Maestro.Client.V0.Address + Maestro.Client.V0.Assets + Maestro.Client.V0.General + Maestro.Client.V0.Pools + Maestro.Client.V0.Scripts + Maestro.Client.V0.Transaction + Maestro.Client.V0.TxManager - Maestro.Types - Maestro.Types.Accounts - Maestro.Types.Address - Maestro.Types.Assets - Maestro.Types.Common - Maestro.Types.Datum - Maestro.Types.Epochs - Maestro.Types.General - Maestro.Types.Pool + Maestro.Types.V0 + Maestro.Types.V0.Accounts + Maestro.Types.V0.Address + Maestro.Types.V0.Assets + Maestro.Types.V0.Common + Maestro.Types.V0.Datum + Maestro.Types.V0.Epochs + Maestro.Types.V0.General + Maestro.Types.V0.Pool -- other-modules: -- other-extensions: diff --git a/src/Maestro/API.hs b/src/Maestro/API/V0.hs similarity index 65% rename from src/Maestro/API.hs rename to src/Maestro/API/V0.hs index 0b7c9b0..414549f 100644 --- a/src/Maestro/API.hs +++ b/src/Maestro/API/V0.hs @@ -1,16 +1,16 @@ -module Maestro.API where +module Maestro.API.V0 where -import Data.Text (Text) -import Maestro.API.Accounts -import Maestro.API.Address -import Maestro.API.Assets -import Maestro.API.Datum -import Maestro.API.Epochs -import Maestro.API.General -import Maestro.API.Pool -import Maestro.API.Scripts -import Maestro.API.Transaction -import Maestro.API.TxManager +import Data.Text (Text) +import Maestro.API.V0.Accounts +import Maestro.API.V0.Address +import Maestro.API.V0.Assets +import Maestro.API.V0.Datum +import Maestro.API.V0.Epochs +import Maestro.API.V0.General +import Maestro.API.V0.Pool +import Maestro.API.V0.Scripts +import Maestro.API.V0.Transaction +import Maestro.API.V0.TxManager import Servant.API import Servant.API.Generic diff --git a/src/Maestro/API/Accounts.hs b/src/Maestro/API/V0/Accounts.hs similarity index 90% rename from src/Maestro/API/Accounts.hs rename to src/Maestro/API/V0/Accounts.hs index 4262273..6faa3ef 100644 --- a/src/Maestro/API/Accounts.hs +++ b/src/Maestro/API/V0/Accounts.hs @@ -1,9 +1,8 @@ -module Maestro.API.Accounts where +module Maestro.API.V0.Accounts where import Data.Text (Text) import Maestro.Client.Core.Pagination -import Maestro.Types.Accounts -import Maestro.Types.Common +import Maestro.Types.V0 import Servant.API import Servant.API.Generic diff --git a/src/Maestro/API/Address.hs b/src/Maestro/API/V0/Address.hs similarity index 84% rename from src/Maestro/API/Address.hs rename to src/Maestro/API/V0/Address.hs index 362a175..1093b9f 100644 --- a/src/Maestro/API/Address.hs +++ b/src/Maestro/API/V0/Address.hs @@ -1,9 +1,8 @@ -module Maestro.API.Address where +module Maestro.API.V0.Address where -import Data.Text (Text) -import Maestro.Types.Address -import Maestro.Types.Common (Utxo) +import Data.Text (Text) import Maestro.Client.Core.Pagination +import Maestro.Types.V0 import Servant.API import Servant.API.Generic diff --git a/src/Maestro/API/Assets.hs b/src/Maestro/API/V0/Assets.hs similarity index 93% rename from src/Maestro/API/Assets.hs rename to src/Maestro/API/V0/Assets.hs index 1c03736..871e7cb 100644 --- a/src/Maestro/API/Assets.hs +++ b/src/Maestro/API/V0/Assets.hs @@ -1,9 +1,8 @@ -module Maestro.API.Assets where +module Maestro.API.V0.Assets where import Data.Text (Text) import Maestro.Client.Core.Pagination -import Maestro.Types.Assets -import Maestro.Types.Common +import Maestro.Types.V0 import Servant.API import Servant.API.Generic diff --git a/src/Maestro/API/Datum.hs b/src/Maestro/API/V0/Datum.hs similarity index 80% rename from src/Maestro/API/Datum.hs rename to src/Maestro/API/V0/Datum.hs index 1a19637..0a57746 100644 --- a/src/Maestro/API/Datum.hs +++ b/src/Maestro/API/V0/Datum.hs @@ -1,7 +1,7 @@ -module Maestro.API.Datum where +module Maestro.API.V0.Datum where import Data.Text (Text) -import Maestro.Types.Datum +import Maestro.Types.V0 import Servant.API import Servant.API.Generic diff --git a/src/Maestro/API/Epochs.hs b/src/Maestro/API/V0/Epochs.hs similarity index 75% rename from src/Maestro/API/Epochs.hs rename to src/Maestro/API/V0/Epochs.hs index 7b07bcd..219fc9a 100644 --- a/src/Maestro/API/Epochs.hs +++ b/src/Maestro/API/V0/Epochs.hs @@ -1,7 +1,6 @@ -module Maestro.API.Epochs where +module Maestro.API.V0.Epochs where -import Maestro.Types.Common (EpochNo) -import Maestro.Types.Epochs +import Maestro.Types.V0 import Servant.API import Servant.API.Generic diff --git a/src/Maestro/API/General.hs b/src/Maestro/API/V0/General.hs similarity index 87% rename from src/Maestro/API/General.hs rename to src/Maestro/API/V0/General.hs index 272def3..ccb78c2 100644 --- a/src/Maestro/API/General.hs +++ b/src/Maestro/API/V0/General.hs @@ -1,6 +1,6 @@ -module Maestro.API.General where +module Maestro.API.V0.General where -import Maestro.Types.General +import Maestro.Types.V0 import Servant.API import Servant.API.Generic diff --git a/src/Maestro/API/Pool.hs b/src/Maestro/API/V0/Pool.hs similarity index 96% rename from src/Maestro/API/Pool.hs rename to src/Maestro/API/V0/Pool.hs index ef38cbb..006ba58 100644 --- a/src/Maestro/API/Pool.hs +++ b/src/Maestro/API/V0/Pool.hs @@ -1,6 +1,6 @@ -module Maestro.API.Pool where +module Maestro.API.V0.Pool where -import Maestro.Types +import Maestro.Types.V0 import Maestro.Client.Core.Pagination import Servant.API import Servant.API.Generic diff --git a/src/Maestro/API/Scripts.hs b/src/Maestro/API/V0/Scripts.hs similarity index 65% rename from src/Maestro/API/Scripts.hs rename to src/Maestro/API/V0/Scripts.hs index 84b6586..46d1536 100644 --- a/src/Maestro/API/Scripts.hs +++ b/src/Maestro/API/V0/Scripts.hs @@ -1,7 +1,7 @@ -module Maestro.API.Scripts where +module Maestro.API.V0.Scripts where -import Data.Text (Text) -import Maestro.Types.Common (Script) +import Data.Text (Text) +import Maestro.Types.V0 import Servant.API import Servant.API.Generic diff --git a/src/Maestro/API/Transaction.hs b/src/Maestro/API/V0/Transaction.hs similarity index 85% rename from src/Maestro/API/Transaction.hs rename to src/Maestro/API/V0/Transaction.hs index 293e523..399f4ae 100644 --- a/src/Maestro/API/Transaction.hs +++ b/src/Maestro/API/V0/Transaction.hs @@ -1,8 +1,8 @@ -module Maestro.API.Transaction where +module Maestro.API.V0.Transaction where -import qualified Data.ByteString as BS -import qualified Data.Text as T -import Maestro.Types.Common +import qualified Data.ByteString as BS +import qualified Data.Text as T +import Maestro.Types.V0 import Servant.API import Servant.API.Generic diff --git a/src/Maestro/API/TxManager.hs b/src/Maestro/API/V0/TxManager.hs similarity index 62% rename from src/Maestro/API/TxManager.hs rename to src/Maestro/API/V0/TxManager.hs index df2fd43..6ca5945 100644 --- a/src/Maestro/API/TxManager.hs +++ b/src/Maestro/API/V0/TxManager.hs @@ -1,8 +1,8 @@ -module Maestro.API.TxManager where +module Maestro.API.V0.TxManager where -import qualified Data.ByteString as BS -import qualified Data.Text as T -import Maestro.Types.Common +import qualified Data.ByteString as BS +import qualified Data.Text as T +import Maestro.Types.V0 import Servant.API import Servant.API.Generic diff --git a/src/Maestro/Client.hs b/src/Maestro/Client.hs deleted file mode 100644 index 74d270f..0000000 --- a/src/Maestro/Client.hs +++ /dev/null @@ -1,29 +0,0 @@ -module Maestro.Client - ( - module Maestro.Client.Accounts - , module Maestro.Client.Address - , module Maestro.Client.Assets - , module Maestro.Client.Core - , module Maestro.Client.Datum - , module Maestro.Client.Env - , module Maestro.Client.Epochs - , module Maestro.Client.General - , module Maestro.Client.Pools - , module Maestro.Client.Scripts - , module Maestro.Client.Transaction - , module Maestro.Client.TxManager - ) where - - -import Maestro.Client.Accounts -import Maestro.Client.Address -import Maestro.Client.Assets -import Maestro.Client.Core -import Maestro.Client.Datum -import Maestro.Client.Env -import Maestro.Client.Epochs -import Maestro.Client.General -import Maestro.Client.Pools -import Maestro.Client.Scripts -import Maestro.Client.Transaction -import Maestro.Client.TxManager diff --git a/src/Maestro/Client/Core.hs b/src/Maestro/Client/Core.hs index 4f7ea44..098cf65 100644 --- a/src/Maestro/Client/Core.hs +++ b/src/Maestro/Client/Core.hs @@ -13,10 +13,10 @@ import Control.Exception (Exception, throwIO) import Data.Aeson (decode) import Data.Text (Text) import Deriving.Aeson -import Maestro.API +import Maestro.API.V0 import Maestro.Client.Core.Pagination import Maestro.Client.Env -import Maestro.Types.Common (LowerFirst) +import Maestro.Types.V0.Common (LowerFirst) import Network.HTTP.Types import Servant.API.Generic (fromServant) import Servant.Client diff --git a/src/Maestro/Client/Env.hs b/src/Maestro/Client/Env.hs index c3763b0..601e48b 100644 --- a/src/Maestro/Client/Env.hs +++ b/src/Maestro/Client/Env.hs @@ -1,8 +1,9 @@ module Maestro.Client.Env ( - MaestroEnv(..) + MaestroEnv (..) + , MaestroNetwork (..) + , MaestroApiVersion (..) , mkMaestroEnv - , MaestroNetwork(..) ) where import Data.Text (Text) @@ -20,13 +21,18 @@ data MaestroEnv = MaestroEnv data MaestroNetwork = Mainnet | Preprod -maestroBaseUrl :: MaestroNetwork -> String -maestroBaseUrl Preprod = "https://preprod.gomaestro-api.org/v0" -maestroBaseUrl Mainnet = "https://mainnet.gomaestro-api.org/v0" +data MaestroApiVersion = V0 | V1 -mkMaestroEnv :: MaestroToken -> MaestroNetwork -> IO MaestroEnv -mkMaestroEnv token nid = do - clientEnv <- servantClientEnv $ maestroBaseUrl nid +-- TODO : Move version check inside. +maestroBaseUrl :: MaestroNetwork -> MaestroApiVersion -> String +maestroBaseUrl Preprod V0 = "https://preprod.gomaestro-api.org/v0" +maestroBaseUrl Preprod V1 = "https://preprod.gomaestro-api.org/v1" +maestroBaseUrl Mainnet V0 = "https://mainnet.gomaestro-api.org/v0" +maestroBaseUrl Mainnet V1 = "https://mainnet.gomaestro-api.org/v1" + +mkMaestroEnv :: MaestroToken -> MaestroNetwork -> MaestroApiVersion -> IO MaestroEnv +mkMaestroEnv token nid apiVersion = do + clientEnv <- servantClientEnv $ maestroBaseUrl nid apiVersion pure $ MaestroEnv { _maeClientEnv = clientEnv, _maeToken = token } servantClientEnv :: String -> IO Servant.ClientEnv diff --git a/src/Maestro/Client/V0.hs b/src/Maestro/Client/V0.hs new file mode 100644 index 0000000..8061670 --- /dev/null +++ b/src/Maestro/Client/V0.hs @@ -0,0 +1,29 @@ +module Maestro.Client.V0 + ( + module Maestro.Client.V0.Accounts + , module Maestro.Client.V0.Address + , module Maestro.Client.V0.Assets + , module Maestro.Client.V0.Datum + , module Maestro.Client.V0.Epochs + , module Maestro.Client.V0.General + , module Maestro.Client.V0.Pools + , module Maestro.Client.V0.Scripts + , module Maestro.Client.V0.Transaction + , module Maestro.Client.V0.TxManager + , module Maestro.Client.Env + , module Maestro.Client.Core + ) where + + +import Maestro.Client.Core +import Maestro.Client.Env +import Maestro.Client.V0.Accounts +import Maestro.Client.V0.Address +import Maestro.Client.V0.Assets +import Maestro.Client.V0.Datum +import Maestro.Client.V0.Epochs +import Maestro.Client.V0.General +import Maestro.Client.V0.Pools +import Maestro.Client.V0.Scripts +import Maestro.Client.V0.Transaction +import Maestro.Client.V0.TxManager diff --git a/src/Maestro/Client/Accounts.hs b/src/Maestro/Client/V0/Accounts.hs similarity index 83% rename from src/Maestro/Client/Accounts.hs rename to src/Maestro/Client/V0/Accounts.hs index 88966a2..eb0588a 100644 --- a/src/Maestro/Client/Accounts.hs +++ b/src/Maestro/Client/V0/Accounts.hs @@ -1,11 +1,11 @@ -module Maestro.Client.Accounts where +module Maestro.Client.V0.Accounts where -import Data.Text (Text) -import Maestro.API -import Maestro.API.Accounts +import Data.Text (Text) +import Maestro.API.V0 +import Maestro.API.V0.Accounts import Maestro.Client.Core import Maestro.Client.Env -import Maestro.Types +import Maestro.Types.V0 import Servant.API.Generic import Servant.Client diff --git a/src/Maestro/Client/Address.hs b/src/Maestro/Client/V0/Address.hs similarity index 87% rename from src/Maestro/Client/Address.hs rename to src/Maestro/Client/V0/Address.hs index d1683b8..3338497 100644 --- a/src/Maestro/Client/Address.hs +++ b/src/Maestro/Client/V0/Address.hs @@ -1,12 +1,11 @@ -module Maestro.Client.Address where +module Maestro.Client.V0.Address where -import Data.Text (Text) -import Maestro.API -import Maestro.API.Address +import Data.Text (Text) +import Maestro.API.V0 +import Maestro.API.V0.Address import Maestro.Client.Core import Maestro.Client.Env -import Maestro.Types.Address -import Maestro.Types.Common (Utxo) +import Maestro.Types.V0 import Servant.API.Generic import Servant.Client diff --git a/src/Maestro/Client/Assets.hs b/src/Maestro/Client/V0/Assets.hs similarity index 93% rename from src/Maestro/Client/Assets.hs rename to src/Maestro/Client/V0/Assets.hs index 9c7d616..ce3307a 100644 --- a/src/Maestro/Client/Assets.hs +++ b/src/Maestro/Client/V0/Assets.hs @@ -1,12 +1,11 @@ -module Maestro.Client.Assets where +module Maestro.Client.V0.Assets where -import Data.Text (Text) -import Maestro.API (_assets) -import Maestro.API.Assets +import Data.Text (Text) +import Maestro.API.V0 (_assets) +import Maestro.API.V0.Assets import Maestro.Client.Core import Maestro.Client.Env -import Maestro.Types.Assets -import Maestro.Types.Common +import Maestro.Types.V0 import Servant.API.Generic import Servant.Client diff --git a/src/Maestro/Client/Datum.hs b/src/Maestro/Client/V0/Datum.hs similarity index 68% rename from src/Maestro/Client/Datum.hs rename to src/Maestro/Client/V0/Datum.hs index 58a6c55..c52a6d6 100644 --- a/src/Maestro/Client/Datum.hs +++ b/src/Maestro/Client/V0/Datum.hs @@ -1,13 +1,13 @@ -module Maestro.Client.Datum +module Maestro.Client.V0.Datum ( getDatumByHash ) where -import Data.Text (Text) -import Maestro.API (_datum) -import Maestro.API.Datum +import Data.Text (Text) +import Maestro.API.V0 (_datum) +import Maestro.API.V0.Datum import Maestro.Client.Core import Maestro.Client.Env -import Maestro.Types +import Maestro.Types.V0 import Servant.API.Generic import Servant.Client diff --git a/src/Maestro/Client/Epochs.hs b/src/Maestro/Client/V0/Epochs.hs similarity index 79% rename from src/Maestro/Client/Epochs.hs rename to src/Maestro/Client/V0/Epochs.hs index d3a07b6..bc53a39 100644 --- a/src/Maestro/Client/Epochs.hs +++ b/src/Maestro/Client/V0/Epochs.hs @@ -1,13 +1,13 @@ -module Maestro.Client.Epochs +module Maestro.Client.V0.Epochs ( getCurrentEpoch , getEpochInfo ) where -import Maestro.API (_epochs) -import Maestro.API.Epochs +import Maestro.API.V0 (_epochs) +import Maestro.API.V0.Epochs import Maestro.Client.Core import Maestro.Client.Env -import Maestro.Types +import Maestro.Types.V0 import Servant.API.Generic import Servant.Client diff --git a/src/Maestro/Client/General.hs b/src/Maestro/Client/V0/General.hs similarity index 85% rename from src/Maestro/Client/General.hs rename to src/Maestro/Client/V0/General.hs index 30103c3..93350e8 100644 --- a/src/Maestro/Client/General.hs +++ b/src/Maestro/Client/V0/General.hs @@ -1,15 +1,15 @@ -module Maestro.Client.General +module Maestro.Client.V0.General ( getChainTip , getSystemStart , getEraHistory , getProtocolParameters ) where -import Maestro.API (_general) -import Maestro.API.General +import Maestro.API.V0 (_general) +import Maestro.API.V0.General import Maestro.Client.Core import Maestro.Client.Env -import Maestro.Types.General +import Maestro.Types.V0 import Servant.API.Generic import Servant.Client diff --git a/src/Maestro/Client/Pools.hs b/src/Maestro/Client/V0/Pools.hs similarity index 91% rename from src/Maestro/Client/Pools.hs rename to src/Maestro/Client/V0/Pools.hs index d6f0057..dcf8251 100644 --- a/src/Maestro/Client/Pools.hs +++ b/src/Maestro/Client/V0/Pools.hs @@ -1,4 +1,4 @@ -module Maestro.Client.Pools +module Maestro.Client.V0.Pools ( listPools, poolBlocks, poolDelegators, @@ -10,12 +10,11 @@ module Maestro.Client.Pools ) where -import Maestro.API -import Maestro.API.Pool +import Maestro.API.V0 +import Maestro.API.V0.Pool import Maestro.Client.Core import Maestro.Client.Env -import Maestro.Types.Common -import Maestro.Types.Pool +import Maestro.Types.V0 import Servant.API.Generic import Servant.Client diff --git a/src/Maestro/Client/Scripts.hs b/src/Maestro/Client/V0/Scripts.hs similarity index 68% rename from src/Maestro/Client/Scripts.hs rename to src/Maestro/Client/V0/Scripts.hs index 6bd2f38..2dd8bfe 100644 --- a/src/Maestro/Client/Scripts.hs +++ b/src/Maestro/Client/V0/Scripts.hs @@ -1,13 +1,13 @@ -module Maestro.Client.Scripts +module Maestro.Client.V0.Scripts ( getScriptByHash ) where -import Data.Text (Text) -import Maestro.API (_scripts) -import Maestro.API.Scripts +import Data.Text (Text) +import Maestro.API.V0 (_scripts) +import Maestro.API.V0.Scripts import Maestro.Client.Core import Maestro.Client.Env -import Maestro.Types +import Maestro.Types.V0 import Servant.API.Generic import Servant.Client diff --git a/src/Maestro/Client/Transaction.hs b/src/Maestro/Client/V0/Transaction.hs similarity index 86% rename from src/Maestro/Client/Transaction.hs rename to src/Maestro/Client/V0/Transaction.hs index 4fe43a3..e62dfbd 100644 --- a/src/Maestro/Client/Transaction.hs +++ b/src/Maestro/Client/V0/Transaction.hs @@ -1,4 +1,4 @@ -module Maestro.Client.Transaction +module Maestro.Client.V0.Transaction ( submitTx, txCbor, txAddress, @@ -6,13 +6,13 @@ module Maestro.Client.Transaction ) where -import qualified Data.ByteString as BS -import Data.Text (Text) -import Maestro.API (_tx) -import Maestro.API.Transaction +import qualified Data.ByteString as BS +import Data.Text (Text) +import Maestro.API.V0 (_tx) +import Maestro.API.V0.Transaction import Maestro.Client.Core import Maestro.Client.Env -import Maestro.Types.Common +import Maestro.Types.V0 import Servant.API.Generic import Servant.Client diff --git a/src/Maestro/Client/TxManager.hs b/src/Maestro/Client/V0/TxManager.hs similarity index 72% rename from src/Maestro/Client/TxManager.hs rename to src/Maestro/Client/V0/TxManager.hs index f0a76a7..f3a9225 100644 --- a/src/Maestro/Client/TxManager.hs +++ b/src/Maestro/Client/V0/TxManager.hs @@ -1,12 +1,12 @@ -module Maestro.Client.TxManager +module Maestro.Client.V0.TxManager ( submitAndMonitorTx ) where -import qualified Data.ByteString as BS -import Data.Text (Text) -import Maestro.API (_txManager) -import Maestro.API.TxManager +import qualified Data.ByteString as BS +import Data.Text (Text) +import Maestro.API.V0 (_txManager) +import Maestro.API.V0.TxManager import Maestro.Client.Core import Maestro.Client.Env import Servant.API.Generic diff --git a/src/Maestro/Types.hs b/src/Maestro/Types.hs deleted file mode 100644 index e2fa7d0..0000000 --- a/src/Maestro/Types.hs +++ /dev/null @@ -1,21 +0,0 @@ --- | Maestro types - -module Maestro.Types - ( module Maestro.Types.Accounts - , module Maestro.Types.Address - , module Maestro.Types.Assets - , module Maestro.Types.Datum - , module Maestro.Types.Epochs - , module Maestro.Types.Common - , module Maestro.Types.General - , module Maestro.Types.Pool - ) where - -import Maestro.Types.Accounts -import Maestro.Types.Address -import Maestro.Types.Assets -import Maestro.Types.Common -import Maestro.Types.Datum -import Maestro.Types.Epochs -import Maestro.Types.General -import Maestro.Types.Pool diff --git a/src/Maestro/Types/V0.hs b/src/Maestro/Types/V0.hs new file mode 100644 index 0000000..7c8a65a --- /dev/null +++ b/src/Maestro/Types/V0.hs @@ -0,0 +1,21 @@ +-- | Maestro types + +module Maestro.Types.V0 + ( module Maestro.Types.V0.Accounts + , module Maestro.Types.V0.Address + , module Maestro.Types.V0.Assets + , module Maestro.Types.V0.Datum + , module Maestro.Types.V0.Epochs + , module Maestro.Types.V0.Common + , module Maestro.Types.V0.General + , module Maestro.Types.V0.Pool + ) where + +import Maestro.Types.V0.Accounts +import Maestro.Types.V0.Address +import Maestro.Types.V0.Assets +import Maestro.Types.V0.Common +import Maestro.Types.V0.Datum +import Maestro.Types.V0.Epochs +import Maestro.Types.V0.General +import Maestro.Types.V0.Pool diff --git a/src/Maestro/Types/Accounts.hs b/src/Maestro/Types/V0/Accounts.hs similarity index 92% rename from src/Maestro/Types/Accounts.hs rename to src/Maestro/Types/V0/Accounts.hs index eae6d23..757955d 100644 --- a/src/Maestro/Types/Accounts.hs +++ b/src/Maestro/Types/V0/Accounts.hs @@ -1,14 +1,13 @@ -module Maestro.Types.Accounts +module Maestro.Types.V0.Accounts ( AccountInfo (..) , AccountHistory (..) , AccountReward (..) , AccountUpdate (..) ) where -import Data.Text (Text) +import Data.Text (Text) import Deriving.Aeson -import Maestro.Types.Common (EpochNo, LowerFirst) -import Maestro.Types.General (SlotNo) +import Maestro.Types.V0.Common (EpochNo, LowerFirst, SlotNo) -- | Information about an account data AccountInfo = AccountInfo diff --git a/src/Maestro/Types/Address.hs b/src/Maestro/Types/V0/Address.hs similarity index 93% rename from src/Maestro/Types/Address.hs rename to src/Maestro/Types/V0/Address.hs index 1c92918..7958dc5 100644 --- a/src/Maestro/Types/Address.hs +++ b/src/Maestro/Types/V0/Address.hs @@ -1,4 +1,4 @@ -module Maestro.Types.Address where +module Maestro.Types.V0.Address where import Data.Text (Text) import Deriving.Aeson diff --git a/src/Maestro/Types/Assets.hs b/src/Maestro/Types/V0/Assets.hs similarity index 90% rename from src/Maestro/Types/Assets.hs rename to src/Maestro/Types/V0/Assets.hs index 53d9696..0dd2871 100644 --- a/src/Maestro/Types/Assets.hs +++ b/src/Maestro/Types/V0/Assets.hs @@ -1,11 +1,11 @@ -module Maestro.Types.Assets where +module Maestro.Types.V0.Assets where -import qualified Data.Aeson as Aeson -import Data.Text (Text) -import Data.Time.Clock.POSIX (POSIXTime) +import qualified Data.Aeson as Aeson +import Data.Text (Text) +import Data.Time.Clock.POSIX (POSIXTime) import Deriving.Aeson -import GHC.Natural (Natural) -import Maestro.Types.Common (BlockHeight, EpochNo, LowerFirst) +import GHC.Natural (Natural) +import Maestro.Types.V0.Common (BlockHeight, EpochNo, LowerFirst) data TokenRegistryMetadata = TokenRegistryMetadata { _tokenRegMetDecimals :: !Integer diff --git a/src/Maestro/Types/Common.hs b/src/Maestro/Types/V0/Common.hs similarity index 96% rename from src/Maestro/Types/Common.hs rename to src/Maestro/Types/V0/Common.hs index 9cc4db5..e49835d 100644 --- a/src/Maestro/Types/Common.hs +++ b/src/Maestro/Types/V0/Common.hs @@ -1,4 +1,4 @@ -module Maestro.Types.Common +module Maestro.Types.V0.Common ( Tx, TxIndex (..), PolicyId (..), @@ -7,6 +7,7 @@ module Maestro.Types.Common EpochNo (..), EpochSize (..), AbsoluteSlot (..), + SlotNo (..), BlockHeight (..), BlockHash (..), TxHash (..), @@ -75,6 +76,11 @@ newtype AbsoluteSlot = AbsoluteSlot {unAbsoluteSlot :: Natural} deriving stock (Show, Eq, Generic) deriving (FromJSON, ToJSON) +-- | The 0-based index for the Ourboros time slot. +newtype SlotNo = SlotNo {unSlotNo :: Word64} + deriving stock (Eq, Ord, Show, Generic) + deriving newtype (Num, Bounded, Enum, Real, Integral, FromJSON, ToJSON) + -- | Block Height newtype BlockHeight = BlockHeight {unBlockHeight :: Natural} deriving stock (Show, Eq, Ord, Generic) diff --git a/src/Maestro/Types/Datum.hs b/src/Maestro/Types/V0/Datum.hs similarity index 74% rename from src/Maestro/Types/Datum.hs rename to src/Maestro/Types/V0/Datum.hs index 9c5cebf..79dbc8c 100644 --- a/src/Maestro/Types/Datum.hs +++ b/src/Maestro/Types/V0/Datum.hs @@ -1,13 +1,13 @@ -- | Module to define types for /\"Datum\"/ endpoints defined at [reference.gomaestro.org](https://reference.gomaestro.org/). -module Maestro.Types.Datum +module Maestro.Types.V0.Datum ( Datum (..) ) where -import Data.Aeson (Value) -import Data.Text (Text) +import Data.Aeson (Value) +import Data.Text (Text) import Deriving.Aeson -import Maestro.Types.Common (LowerFirst) +import Maestro.Types.V0.Common (LowerFirst) -- | Details of datum when queried by it's hash. data Datum = Datum diff --git a/src/Maestro/Types/Epochs.hs b/src/Maestro/Types/V0/Epochs.hs similarity index 79% rename from src/Maestro/Types/Epochs.hs rename to src/Maestro/Types/V0/Epochs.hs index 2c01bdd..35b79f2 100644 --- a/src/Maestro/Types/Epochs.hs +++ b/src/Maestro/Types/V0/Epochs.hs @@ -1,14 +1,14 @@ -module Maestro.Types.Epochs ( EpochInfoFees (..), CurrentEpochInfo (..), EpochInfo (..) ) where +module Maestro.Types.V0.Epochs ( EpochInfoFees (..), CurrentEpochInfo (..), EpochInfo (..) ) where -import Data.Aeson (FromJSON (parseJSON), toEncoding, - toJSON, withText) -import Data.Text (unpack) -import Data.Time.Clock.POSIX (POSIXTime) -import Data.Word (Word64) +import Data.Aeson (FromJSON (parseJSON), toEncoding, + toJSON, withText) +import Data.Text (unpack) +import Data.Time.Clock.POSIX (POSIXTime) +import Data.Word (Word64) import Deriving.Aeson -import Maestro.Types.Common -import Numeric.Natural (Natural) -import Text.Read (readMaybe) +import Maestro.Types.V0.Common +import Numeric.Natural (Natural) +import Text.Read (readMaybe) -- | Sum of all the fees within the epoch in lovelaces. newtype EpochInfoFees = EpochInfoFees Natural diff --git a/src/Maestro/Types/General.hs b/src/Maestro/Types/V0/General.hs similarity index 91% rename from src/Maestro/Types/General.hs rename to src/Maestro/Types/V0/General.hs index f55e611..bb8f33d 100644 --- a/src/Maestro/Types/General.hs +++ b/src/Maestro/Types/V0/General.hs @@ -1,10 +1,9 @@ -- | Module to define types for /\"General\"/ endpoints defined at [reference.gomaestro.org](https://reference.gomaestro.org/). -module Maestro.Types.General +module Maestro.Types.V0.General ( -- * Types for @/system-start@ endpoint SystemStart (..) -- * Types for @/era-history@ endpoint - , SlotNo (..) , EraSummary (..) , EraParameters (..) , EraBound (..) @@ -21,20 +20,20 @@ module Maestro.Types.General , ChainTip (..) ) where -import Control.Monad (unless, when) -import Data.Aeson (FromJSON (parseJSON), toEncoding, toJSON, - withText) -import Data.Map.Strict (Map) -import Data.Ratio (denominator, numerator, (%)) -import Data.Text (Text) -import qualified Data.Text as Txt -import qualified Data.Text.Read as TxtRead -import Data.Time (LocalTime, NominalDiffTime) -import Data.Word (Word64) +import Control.Monad (unless, when) +import Data.Aeson (FromJSON (parseJSON), toEncoding, + toJSON, withText) +import Data.Map.Strict (Map) +import Data.Ratio (denominator, numerator, (%)) +import Data.Text (Text) +import qualified Data.Text as Txt +import qualified Data.Text.Read as TxtRead +import Data.Time (LocalTime, NominalDiffTime) +import Data.Word (Word64) import Deriving.Aeson -import Maestro.Types.Common (BlockHash, EpochNo, EpochSize, - LowerFirst) -import Numeric.Natural (Natural) +import Maestro.Types.V0.Common (BlockHash, EpochNo, EpochSize, + LowerFirst, SlotNo) +import Numeric.Natural (Natural) ------------------------------------------------------------------ -- Types for @/system-start@ endpoint. @@ -49,11 +48,6 @@ newtype SystemStart = SystemStart { _systemStartTime :: LocalTime } -- Types for @/era-history@ endpoint ------------------------------------------------------------------ --- | The 0-based index for the Ourboros time slot. -newtype SlotNo = SlotNo {unSlotNo :: Word64} - deriving stock (Eq, Ord, Show, Generic) - deriving newtype (Num, Bounded, Enum, Real, Integral, FromJSON, ToJSON) - -- | Network era summary. data EraSummary = EraSummary { _eraSummaryStart :: !EraBound diff --git a/src/Maestro/Types/Pool.hs b/src/Maestro/Types/V0/Pool.hs similarity index 97% rename from src/Maestro/Types/Pool.hs rename to src/Maestro/Types/V0/Pool.hs index 13fa772..87f9d08 100644 --- a/src/Maestro/Types/Pool.hs +++ b/src/Maestro/Types/V0/Pool.hs @@ -1,4 +1,4 @@ -module Maestro.Types.Pool +module Maestro.Types.V0.Pool ( ActiveStake (..), DelegatorInfo (..), PoolListInfo (..), @@ -14,11 +14,11 @@ module Maestro.Types.Pool ) where -import Data.Text (Text) -import Data.Time.Clock.POSIX (POSIXTime) +import Data.Text (Text) +import Data.Time.Clock.POSIX (POSIXTime) import Deriving.Aeson -import GHC.Natural (Natural) -import Maestro.Types.Common +import GHC.Natural (Natural) +import Maestro.Types.V0.Common data PoolId diff --git a/src/Maestro/Types/Version.hs b/src/Maestro/Types/Version.hs new file mode 100644 index 0000000..6196ed9 --- /dev/null +++ b/src/Maestro/Types/Version.hs @@ -0,0 +1,6 @@ +module Maestro.Types.Version ( + ApiVersion (..) + ) where + + +data ApiVersion = V0 | V1 diff --git a/test/Maestro/Test/Datum.hs b/test/Maestro/Test/Datum.hs index 5c1870e..3199480 100644 --- a/test/Maestro/Test/Datum.hs +++ b/test/Maestro/Test/Datum.hs @@ -5,7 +5,7 @@ import Test.Hspec import Text.RawString.QQ import Data.ByteString.Lazy (ByteString) -import Maestro.Types +import Maestro.Types.V0 spec_general :: Spec spec_general = do diff --git a/test/Maestro/Test/Epochs.hs b/test/Maestro/Test/Epochs.hs index d287ea6..ba80cbb 100644 --- a/test/Maestro/Test/Epochs.hs +++ b/test/Maestro/Test/Epochs.hs @@ -5,7 +5,7 @@ import Test.Hspec import Text.RawString.QQ import Data.ByteString.Lazy (ByteString) -import Maestro.Types +import Maestro.Types.V0 spec_general :: Spec spec_general = do diff --git a/test/Maestro/Test/General.hs b/test/Maestro/Test/General.hs index 95a42a1..ee17d07 100644 --- a/test/Maestro/Test/General.hs +++ b/test/Maestro/Test/General.hs @@ -9,7 +9,7 @@ import Text.RawString.QQ import Data.ByteString.Lazy (ByteString) import Data.Time.Calendar.OrdinalDate (fromOrdinalDate) -import Maestro.Types +import Maestro.Types.V0 spec_general :: Spec spec_general = do diff --git a/test/Maestro/Test/Pool.hs b/test/Maestro/Test/Pool.hs index b2b2017..ba89dcc 100644 --- a/test/Maestro/Test/Pool.hs +++ b/test/Maestro/Test/Pool.hs @@ -6,7 +6,7 @@ import Test.Hspec import Text.RawString.QQ import Data.ByteString.Lazy (ByteString) -import Maestro.Types +import Maestro.Types.V0 spec_pool :: Spec spec_pool = do diff --git a/test/Maestro/Test/Transaction.hs b/test/Maestro/Test/Transaction.hs index 30f2f7a..cbb58b2 100644 --- a/test/Maestro/Test/Transaction.hs +++ b/test/Maestro/Test/Transaction.hs @@ -6,7 +6,7 @@ import Test.Hspec import Text.RawString.QQ import Data.ByteString.Lazy (ByteString) -import Maestro.Types +import Maestro.Types.V0 spec_pool :: Spec spec_pool = do From c2fbc1278b55699af32e3abe7f545b61f297c5a2 Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Wed, 5 Jul 2023 17:35:28 +0530 Subject: [PATCH 03/24] Feat 30: V1 General endpoints --- src/Maestro/API/V1/General.hs | 26 ++++ src/Maestro/Types/V0/Common.hs | 2 +- src/Maestro/Types/V1.hs | 11 ++ src/Maestro/Types/V1/Common.hs | 17 +++ src/Maestro/Types/V1/General.hs | 258 ++++++++++++++++++++++++++++++++ src/Maestro/Types/Version.hs | 6 - 6 files changed, 313 insertions(+), 7 deletions(-) create mode 100644 src/Maestro/API/V1/General.hs create mode 100644 src/Maestro/Types/V1.hs create mode 100644 src/Maestro/Types/V1/Common.hs create mode 100644 src/Maestro/Types/V1/General.hs delete mode 100644 src/Maestro/Types/Version.hs diff --git a/src/Maestro/API/V1/General.hs b/src/Maestro/API/V1/General.hs new file mode 100644 index 0000000..82093ce --- /dev/null +++ b/src/Maestro/API/V1/General.hs @@ -0,0 +1,26 @@ +module Maestro.API.V1.General where + +import Maestro.Types.V1 +import Servant.API +import Servant.API.Generic + +data GeneralAPI route = + GeneralAPI + { + _systemStart + :: route + :- "system-start" + :> Get '[JSON] SystemStart + , _eraHistory + :: route + :- "era-history" + :> Get '[JSON] EraSummaries + , _protocolParams + :: route + :- "protocol-params" + :> Get '[JSON] ProtocolParameters + , _chainTip + :: route + :- "chain-tip" + :> Get '[JSON] ChainTip + } deriving Generic diff --git a/src/Maestro/Types/V0/Common.hs b/src/Maestro/Types/V0/Common.hs index e49835d..59ea986 100644 --- a/src/Maestro/Types/V0/Common.hs +++ b/src/Maestro/Types/V0/Common.hs @@ -88,7 +88,7 @@ newtype BlockHeight = BlockHeight {unBlockHeight :: Natural} -- | Hash of the block. newtype BlockHash = BlockHash {unBlockHash :: Text} - deriving stock (Show, Eq, Generic) + deriving stock (Show, Eq, Ord, Generic) deriving (FromJSON, ToJSON) -- | Hash of the Transaction. diff --git a/src/Maestro/Types/V1.hs b/src/Maestro/Types/V1.hs new file mode 100644 index 0000000..ad43e58 --- /dev/null +++ b/src/Maestro/Types/V1.hs @@ -0,0 +1,11 @@ +-- | Maestro types + +module Maestro.Types.V1 + ( module Maestro.Types.V0.Common + , module Maestro.Types.V1.Common + , module Maestro.Types.V1.General + ) where + +import Maestro.Types.V0.Common +import Maestro.Types.V1.Common +import Maestro.Types.V1.General diff --git a/src/Maestro/Types/V1/Common.hs b/src/Maestro/Types/V1/Common.hs new file mode 100644 index 0000000..40efed6 --- /dev/null +++ b/src/Maestro/Types/V1/Common.hs @@ -0,0 +1,17 @@ +module Maestro.Types.V1.Common + ( LastUpdated (..), + ) +where + +import Deriving.Aeson +import Maestro.Types.V0.Common + +-- | Details of the most recent block processed by the indexer (aka chain tip); that is, the data returned is correct as of this block in time. +data LastUpdated = LastUpdated + { _lastUpdatedBlockHash :: !BlockHash + -- ^ Hash of the latest block. + , _lastUpdatedBlockSlot :: !SlotNo + -- ^ Slot number for the tip. + } + deriving stock (Eq, Ord, Show, Generic) + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_lastUpdated", CamelToSnake]] LastUpdated diff --git a/src/Maestro/Types/V1/General.hs b/src/Maestro/Types/V1/General.hs new file mode 100644 index 0000000..285a670 --- /dev/null +++ b/src/Maestro/Types/V1/General.hs @@ -0,0 +1,258 @@ +-- | Module to define types for /\"General\"/ endpoints defined at [reference.gomaestro.org](https://reference.gomaestro.org/). + +module Maestro.Types.V1.General + ( -- * Types for @/system-start@ endpoint + SystemStart (..) + -- * Types for @/era-history@ endpoint + , EraSummaries (..) + , EraSummaryData (..) + , EraParameters (..) + , EraBound (..) + -- * Types for @/protocol-params@ endpoint + , ProtocolVersion (..) + , MemoryStepsWith (..) + , CostModel (..) + , CostModels (..) + , MaestroRational (..) + , textToMaestroRational + , textFromMaestroRational + , ProtocolParameters (..) + , ProtocolParametersData (..) + -- * Types for @/chain-tip@ endpoint + , ChainTip (..) + , ChainTipData (..) + ) where + +import Control.Monad (unless, when) +import Data.Aeson (FromJSON (parseJSON), toEncoding, + toJSON, withText) +import Data.Map.Strict (Map) +import Data.Ratio (denominator, numerator, (%)) +import Data.Text (Text) +import qualified Data.Text as Txt +import qualified Data.Text.Read as TxtRead +import Data.Time (LocalTime, NominalDiffTime) +import Data.Word (Word64) +import Deriving.Aeson +import Maestro.Types.V0.Common (BlockHash, EpochNo, EpochSize, + LowerFirst, SlotNo) +import Maestro.Types.V1.Common (LastUpdated (..)) +import Numeric.Natural (Natural) + +------------------------------------------------------------------ +-- Types for @/system-start@ endpoint. +------------------------------------------------------------------ + +-- | Network start time since genesis. +data SystemStart = SystemStart + { _systemStartData :: !LocalTime + , _systemStartLastUpdated :: !LastUpdated + } + deriving stock (Eq, Ord, Show, Generic) + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_systemStart", CamelToSnake]] SystemStart + +------------------------------------------------------------------ +-- Types for @/era-history@ endpoint +------------------------------------------------------------------ + +-- | Network era summaries. +data EraSummaries = EraSummaries + { _eraSummariesData :: ![EraSummaryData] + , _eraSummariesLastUpdated :: !LastUpdated + } + deriving stock (Eq, Show, Generic) + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_eraSummaries", LowerFirst]] EraSummaries + +-- | Network era summary. +data EraSummaryData = EraSummaryData + { _eraSummaryDataStart :: !EraBound + -- ^ Start of this era. + , _eraSummaryDataEnd :: !(Maybe EraBound) + -- ^ End of this era. + , _eraSummaryDataParameters :: !EraParameters + -- ^ Parameters of this era. + } + deriving stock (Eq, Show, Generic) + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_eraSummaryData", LowerFirst]] EraSummaryData + +-- | Parameters for a network era which can vary between hardforks. +data EraParameters = EraParameters + { _eraParametersEpochLength :: !EpochSize + -- ^ Number of slots in an epoch. + , _eraParametersSlotLength :: !NominalDiffTime + -- ^ How long a slot lasts. + , _eraParametersSafeZone :: !(Maybe Word64) + -- ^ Number of slots from the tip of the ledger in which a hardfork will not happen. + } + deriving stock (Eq, Show, Generic) + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_eraParameters", CamelToSnake]] EraParameters + +-- | Bounds of an era. +data EraBound = EraBound + { _eraBoundEpoch :: !EpochNo + -- ^ Epoch number bounding this era. + , _eraBoundSlot :: !SlotNo + -- ^ Absolute slot number bounding this era. + , _eraBoundTime :: !NominalDiffTime + -- ^ Time relative to the start time of the network. + } + deriving stock (Eq, Show, Generic) + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_eraBound", LowerFirst]] EraBound + +------------------------------------------------------------------ +-- Types for @/protocol-params@ endpoint. +------------------------------------------------------------------ + +-- | Current accepted protocol version. An increase in the major version indicates a hard fork, and the minor version a soft fork (meaning old software can validate but not produce new blocks). +data ProtocolVersion = ProtocolVersion + { _protocolVersionMajor :: !Natural + -- ^ Accepted protocol major version. + , _protocolVersionMinor :: !Natural + -- ^ Accepted protocol minor version. + } + deriving stock (Eq, Show, Generic) + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_protocolVersion", LowerFirst]] ProtocolVersion + +-- | Pair of memory & steps for the given type. +data MemoryStepsWith i = MemoryStepsWith + { _memoryStepsWithMemory :: !i + , _memoryStepsWithSteps :: !i + } + deriving stock (Eq, Show, Generic) + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_memoryStepsWith", LowerFirst]] (MemoryStepsWith i) + +-- | A cost model is a vector of coefficients that are used to compute the execution units required to execute a script. Its specifics depend on specific versions of the Plutus interpreter it is used with. +newtype CostModel = CostModel (Map Text Integer) + deriving (Eq, Show) + deriving newtype (ToJSON, FromJSON) + +-- | Cost models (see `CostModel`) for script languages that use them. +data CostModels = CostModels + { _costModelsPlutusV1 :: !CostModel + , _costModelsPlutusV2 :: !CostModel + } + deriving stock (Eq, Show, Generic) + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_costModels", Rename "PlutusV1" "plutus:v1", Rename "PlutusV2" "plutus:v2"]] CostModels + +-- | Maestro's represents rational numbers as string with numerator and denominator demarcated by \'\/\', example: @"1/3"@. +newtype MaestroRational = MaestroRational { unMaestroRational :: Rational } + deriving stock Eq + +instance Show MaestroRational where + show (MaestroRational r) = show (numerator r) ++ '/' : show (denominator r) + +-- | Get original `Text` from `MaestroRational`. +textFromMaestroRational :: MaestroRational -> Text +textFromMaestroRational = Txt.pack . show . unMaestroRational + +-- | Parses given `Text` to `MaestroRational`. +textToMaestroRational :: Text -> Either String MaestroRational +textToMaestroRational ratTxt = + case TxtRead.signed rationalReader ratTxt of + Right (rat, remainingTxt) -> if Txt.null remainingTxt + then pure $ MaestroRational rat + else Left "Expected full string to be parsed" + Left e -> Left e + where + rationalReader :: TxtRead.Reader Rational + rationalReader ratTxt' = do + (numr, remaining) <- TxtRead.decimal ratTxt' + (nextChar, denmrTxt) <- maybe + (Left "Unexpected end of string after parsing numerator") + pure + $ Txt.uncons remaining + unless (nextChar == '/') + . Left + $ "Expected numerator to be immediately followed by '/', but it was followed by: " ++ show nextChar + (denmr, finalRemaining) <- TxtRead.decimal denmrTxt + when (denmr == 0) + $ Left "Expected non-zero denominator" + pure (numr % denmr, finalRemaining) + +instance ToJSON MaestroRational where + toEncoding = toEncoding . textFromMaestroRational + toJSON = toJSON . textFromMaestroRational + +instance FromJSON MaestroRational where + parseJSON = withText "MaestroRational" $ \ratTxt -> either fail pure $ textToMaestroRational ratTxt + +-- See `ProtocolParametersData`. +data ProtocolParameters = ProtocolParameters + { _protocolParametersData :: !ProtocolParametersData + , _protocolParametersLastUpdated :: !LastUpdated + } + +-- | Protocol parameters for the latest epoch. +data ProtocolParametersData = ProtocolParametersData + { _protocolParametersDataProtocolVersion :: !ProtocolVersion + -- ^ See `ProtocolVersion`. + , _protocolParametersDataMinFeeConstant :: !Natural + -- ^ The linear factor for the minimum fee calculation for given epoch /AKA/ @min_fee_b@ and @tx_fee_fixed@. + , _protocolParametersDataMinFeeCoefficient :: !Natural + -- ^ The constant factor for the minimum fee calculation /AKA/ @min_fee_a@ and @tx_fee_per_byte@. + , _protocolParametersDataMaxBlockBodySize :: !Natural + -- ^ Maximum block body size. + , _protocolParametersDataMaxBlockHeaderSize :: !Natural + -- ^ Maximum block header size. + , _protocolParametersDataMaxTxSize :: !Natural + -- ^ Maximum transaction size. + , _protocolParametersDataStakeKeyDeposit :: !Natural + -- The deposit required to register a stake address. + , _protocolParametersDataPoolDeposit :: !Natural + -- ^ The amount of a pool registration deposit in lovelaces /AKA/ @stake_pool_deposit@. + , _protocolParametersDataPoolRetirementEpochBound :: !EpochNo + -- ^ The maximum number of epochs into the future that stake pools are permitted to schedule a retirement /AKA/ @pool_retire_max_epoch@, @e_max@. + , _protocolParametersDataDesiredNumberOfPools :: !Natural + -- The equilibrium target number of stake pools. This is the \"k\" incentives parameter from the design document, /AKA/ @n_opt@, @stake_pool_target@. + , _protocolParametersDataPoolInfluence :: !MaestroRational + -- The influence of the pledge in stake pool rewards. This is the \"a_0\" incentives parameter from the design document. + , _protocolParametersDataMonetaryExpansion :: !MaestroRational + -- ^ The monetary expansion rate. This determines the fraction of the reserves that are added to the fee pot each epoch. This is the \"rho\" incentives parameter from the design document. + , _protocolParametersDataTreasuryExpansion :: !MaestroRational + -- ^ The fraction of the fee pot each epoch that goes to the treasury. This is the \"tau\" incentives parameter from the design document, /AKA/ @treasury_cut@. + , _protocolParametersDataMinPoolCost :: !Natural + -- ^ The minimum value that stake pools are permitted to declare for their cost parameter. + , _protocolParametersDataPrices :: !(MemoryStepsWith MaestroRational) + -- ^ The price per unit memory & price per reduction step corresponding to abstract notions of the relative memory usage and script execution steps respectively. + , _protocolParametersDataMaxExecutionUnitsPerTransaction :: !(MemoryStepsWith Natural) + -- ^ The maximum number of execution memory & steps allowed to be used in a single transaction. + , _protocolParametersDataMaxExecutionUnitsPerBlock :: !(MemoryStepsWith Natural) + -- ^ The maximum number of execution memory & steps allowed to be used in a single block. + , _protocolParametersDataMaxValueSize :: !Natural + -- ^ Maximum size of the /value/ part of an output in a serialized transaction. + , _protocolParametersDataCollateralPercentage :: !Natural + -- ^ The percentage of the transactions fee which must be provided as collateral when including non-native scripts. + , _protocolParametersDataMaxCollateralInputs :: !Natural + -- ^ The maximum number of collateral inputs allowed in a transaction. + , _protocolParametersDataCoinsPerUtxoByte :: !Natural + -- ^ The cost per UTxO size. Cost per UTxO /word/ for Alozno. Cost per UTxO /byte/ for Babbage and later. + , _protocolParametersDataCostModels :: !CostModels + -- ^ See `CostModels`. + } + deriving stock (Eq, Show, Generic) + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_protocolParametersData", CamelToSnake]] ProtocolParametersData + +------------------------------------------------------------------ +-- Types for @/chain-tip@ endpoint. +------------------------------------------------------------------ + +-- | Details about the most recently adopted block. +data ChainTipData = ChainTipData + { _chainTipDataBlockHash :: !BlockHash + -- ^ Hash of this most recent block. + , _chainTipDataSlot :: !SlotNo + -- ^ Slot number for this most recent block. + , _chainTipDataHeight :: !Word64 + -- ^ Block number (height) of this most recent block. + } + deriving stock (Eq, Show, Generic) + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_chainTipData", CamelToSnake]] ChainTipData + + +-- | See `ChainTipData`. +data ChainTip = ChainTip + { _chainTipData :: !ChainTipData + , _chainTipLastUpdated :: !LastUpdated + } + deriving stock (Eq, Show, Generic) + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_chainTip", CamelToSnake]] ChainTip diff --git a/src/Maestro/Types/Version.hs b/src/Maestro/Types/Version.hs deleted file mode 100644 index 6196ed9..0000000 --- a/src/Maestro/Types/Version.hs +++ /dev/null @@ -1,6 +0,0 @@ -module Maestro.Types.Version ( - ApiVersion (..) - ) where - - -data ApiVersion = V0 | V1 From 8a41d35d571bd2aceefaaea815259d34bfb4b117 Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Wed, 5 Jul 2023 18:31:05 +0530 Subject: [PATCH 04/24] Feat 30: Client bifurcation --- maestro-sdk.cabal | 8 ++- src/Maestro/API/V0/Accounts.hs | 4 +- src/Maestro/API/V0/Address.hs | 2 +- src/Maestro/API/V0/Assets.hs | 2 +- src/Maestro/API/V0/Pool.hs | 8 +-- src/Maestro/Client/{Core.hs => Error.hs} | 23 ++----- src/Maestro/Client/V0.hs | 11 ++-- src/Maestro/Client/V0/Accounts.hs | 2 +- src/Maestro/Client/V0/Address.hs | 2 +- src/Maestro/Client/V0/Assets.hs | 6 +- src/Maestro/Client/V0/Core.hs | 20 ++++++ src/Maestro/Client/V0/Core/Pagination.hs | 64 +++++++++++++++++++ src/Maestro/Client/V0/Datum.hs | 6 +- src/Maestro/Client/V0/Epochs.hs | 2 +- src/Maestro/Client/V0/General.hs | 4 +- src/Maestro/Client/{Core => V0}/Pagination.hs | 2 +- src/Maestro/Client/V0/Pools.hs | 2 +- src/Maestro/Client/V0/Scripts.hs | 2 +- src/Maestro/Client/V0/Transaction.hs | 2 +- src/Maestro/Client/V0/TxManager.hs | 2 +- 20 files changed, 124 insertions(+), 50 deletions(-) rename src/Maestro/Client/{Core.hs => Error.hs} (71%) create mode 100644 src/Maestro/Client/V0/Core.hs create mode 100644 src/Maestro/Client/V0/Core/Pagination.hs rename src/Maestro/Client/{Core => V0}/Pagination.hs (97%) diff --git a/maestro-sdk.cabal b/maestro-sdk.cabal index be93cce..d87b4ae 100644 --- a/maestro-sdk.cabal +++ b/maestro-sdk.cabal @@ -51,16 +51,18 @@ library Maestro.API.V0.Transaction Maestro.API.V0.TxManager + Maestro.Client.Env + Maestro.Client.Error Maestro.Client.V0 - Maestro.Client.Core - Maestro.Client.Core.Pagination + Maestro.Client.V0.Core + Maestro.Client.V0.Core.Pagination Maestro.Client.V0.Datum - Maestro.Client.Env Maestro.Client.V0.Epochs Maestro.Client.V0.Accounts Maestro.Client.V0.Address Maestro.Client.V0.Assets Maestro.Client.V0.General + Maestro.Client.V0.Pagination Maestro.Client.V0.Pools Maestro.Client.V0.Scripts Maestro.Client.V0.Transaction diff --git a/src/Maestro/API/V0/Accounts.hs b/src/Maestro/API/V0/Accounts.hs index 6faa3ef..fca412d 100644 --- a/src/Maestro/API/V0/Accounts.hs +++ b/src/Maestro/API/V0/Accounts.hs @@ -1,7 +1,7 @@ module Maestro.API.V0.Accounts where -import Data.Text (Text) -import Maestro.Client.Core.Pagination +import Data.Text (Text) +import Maestro.Client.V0.Core.Pagination import Maestro.Types.V0 import Servant.API import Servant.API.Generic diff --git a/src/Maestro/API/V0/Address.hs b/src/Maestro/API/V0/Address.hs index 1093b9f..2364288 100644 --- a/src/Maestro/API/V0/Address.hs +++ b/src/Maestro/API/V0/Address.hs @@ -1,7 +1,7 @@ module Maestro.API.V0.Address where import Data.Text (Text) -import Maestro.Client.Core.Pagination +import Maestro.Client.V0.Core.Pagination import Maestro.Types.V0 import Servant.API import Servant.API.Generic diff --git a/src/Maestro/API/V0/Assets.hs b/src/Maestro/API/V0/Assets.hs index 871e7cb..d5ec5d9 100644 --- a/src/Maestro/API/V0/Assets.hs +++ b/src/Maestro/API/V0/Assets.hs @@ -1,7 +1,7 @@ module Maestro.API.V0.Assets where import Data.Text (Text) -import Maestro.Client.Core.Pagination +import Maestro.Client.V0.Core.Pagination import Maestro.Types.V0 import Servant.API import Servant.API.Generic diff --git a/src/Maestro/API/V0/Pool.hs b/src/Maestro/API/V0/Pool.hs index 006ba58..bee49f1 100644 --- a/src/Maestro/API/V0/Pool.hs +++ b/src/Maestro/API/V0/Pool.hs @@ -1,9 +1,9 @@ module Maestro.API.V0.Pool where -import Maestro.Types.V0 -import Maestro.Client.Core.Pagination -import Servant.API -import Servant.API.Generic +import Maestro.Client.V0.Core.Pagination +import Maestro.Types.V0 +import Servant.API +import Servant.API.Generic data PoolAPI route = PoolAPI { _listPools :: diff --git a/src/Maestro/Client/Core.hs b/src/Maestro/Client/Error.hs similarity index 71% rename from src/Maestro/Client/Core.hs rename to src/Maestro/Client/Error.hs index 098cf65..08c4502 100644 --- a/src/Maestro/Client/Core.hs +++ b/src/Maestro/Client/Error.hs @@ -1,26 +1,19 @@ {-# LANGUAGE DeriveAnyClass #-} -module Maestro.Client.Core +module Maestro.Client.Error ( ApiError (..) - , apiV0Client , MaestroError (..) , fromServantClientError - , module Maestro.Client.Core.Pagination ) where -import Control.Exception (Exception, throwIO) -import Data.Aeson (decode) -import Data.Text (Text) +import Control.Exception (Exception) +import Data.Aeson (decode) +import Data.Text (Text) import Deriving.Aeson -import Maestro.API.V0 -import Maestro.Client.Core.Pagination -import Maestro.Client.Env -import Maestro.Types.V0.Common (LowerFirst) +import Maestro.Types.V0.Common (LowerFirst) import Network.HTTP.Types -import Servant.API.Generic (fromServant) import Servant.Client -import Servant.Client.Generic -- | In cases of failure, at times, Maestro returns a JSON object with an error message. data ApiError = ApiError @@ -82,9 +75,3 @@ fromServantClientError e = case e of case decode body of Just (m :: Text) -> m Nothing -> mempty - -apiV0ClientAuth :: MaestroEnv -> MaestroApiV0Auth (AsClientT IO) -apiV0ClientAuth MaestroEnv{..} = genericClientHoist $ \x -> runClientM x _maeClientEnv >>= either (throwIO . fromServantClientError) pure - -apiV0Client :: MaestroEnv -> MaestroApiV0 (AsClientT IO) -apiV0Client mEnv@MaestroEnv {..} = fromServant $ _apiV0 (apiV0ClientAuth mEnv) _maeToken diff --git a/src/Maestro/Client/V0.hs b/src/Maestro/Client/V0.hs index 8061670..a5239ca 100644 --- a/src/Maestro/Client/V0.hs +++ b/src/Maestro/Client/V0.hs @@ -1,8 +1,10 @@ module Maestro.Client.V0 - ( - module Maestro.Client.V0.Accounts + ( module Maestro.Client.Env + , module Maestro.Client.Error + , module Maestro.Client.V0.Accounts , module Maestro.Client.V0.Address , module Maestro.Client.V0.Assets + , module Maestro.Client.V0.Core , module Maestro.Client.V0.Datum , module Maestro.Client.V0.Epochs , module Maestro.Client.V0.General @@ -10,16 +12,15 @@ module Maestro.Client.V0 , module Maestro.Client.V0.Scripts , module Maestro.Client.V0.Transaction , module Maestro.Client.V0.TxManager - , module Maestro.Client.Env - , module Maestro.Client.Core ) where -import Maestro.Client.Core import Maestro.Client.Env +import Maestro.Client.Error import Maestro.Client.V0.Accounts import Maestro.Client.V0.Address import Maestro.Client.V0.Assets +import Maestro.Client.V0.Core import Maestro.Client.V0.Datum import Maestro.Client.V0.Epochs import Maestro.Client.V0.General diff --git a/src/Maestro/Client/V0/Accounts.hs b/src/Maestro/Client/V0/Accounts.hs index eb0588a..89f11e5 100644 --- a/src/Maestro/Client/V0/Accounts.hs +++ b/src/Maestro/Client/V0/Accounts.hs @@ -3,8 +3,8 @@ module Maestro.Client.V0.Accounts where import Data.Text (Text) import Maestro.API.V0 import Maestro.API.V0.Accounts -import Maestro.Client.Core import Maestro.Client.Env +import Maestro.Client.V0.Core import Maestro.Types.V0 import Servant.API.Generic import Servant.Client diff --git a/src/Maestro/Client/V0/Address.hs b/src/Maestro/Client/V0/Address.hs index 3338497..5ec9fef 100644 --- a/src/Maestro/Client/V0/Address.hs +++ b/src/Maestro/Client/V0/Address.hs @@ -3,8 +3,8 @@ module Maestro.Client.V0.Address where import Data.Text (Text) import Maestro.API.V0 import Maestro.API.V0.Address -import Maestro.Client.Core import Maestro.Client.Env +import Maestro.Client.V0.Core import Maestro.Types.V0 import Servant.API.Generic import Servant.Client diff --git a/src/Maestro/Client/V0/Assets.hs b/src/Maestro/Client/V0/Assets.hs index ce3307a..85e4233 100644 --- a/src/Maestro/Client/V0/Assets.hs +++ b/src/Maestro/Client/V0/Assets.hs @@ -1,10 +1,10 @@ module Maestro.Client.V0.Assets where -import Data.Text (Text) -import Maestro.API.V0 (_assets) +import Data.Text (Text) +import Maestro.API.V0 (_assets) import Maestro.API.V0.Assets -import Maestro.Client.Core import Maestro.Client.Env +import Maestro.Client.V0.Core import Maestro.Types.V0 import Servant.API.Generic import Servant.Client diff --git a/src/Maestro/Client/V0/Core.hs b/src/Maestro/Client/V0/Core.hs new file mode 100644 index 0000000..1acd9ad --- /dev/null +++ b/src/Maestro/Client/V0/Core.hs @@ -0,0 +1,20 @@ +module Maestro.Client.V0.Core + ( apiV0Client + , module Maestro.Client.V0.Core.Pagination + ) where + +import Control.Exception (throwIO) +import Maestro.API.V0 +import Maestro.Client.Env +import Maestro.Client.Error (fromServantClientError) +import Maestro.Client.V0.Core.Pagination +import Servant.API.Generic (fromServant) +import Servant.Client +import Servant.Client.Generic + + +apiV0ClientAuth :: MaestroEnv -> MaestroApiV0Auth (AsClientT IO) +apiV0ClientAuth MaestroEnv{..} = genericClientHoist $ \x -> runClientM x _maeClientEnv >>= either (throwIO . fromServantClientError) pure + +apiV0Client :: MaestroEnv -> MaestroApiV0 (AsClientT IO) +apiV0Client mEnv@MaestroEnv {..} = fromServant $ _apiV0 (apiV0ClientAuth mEnv) _maeToken diff --git a/src/Maestro/Client/V0/Core/Pagination.hs b/src/Maestro/Client/V0/Core/Pagination.hs new file mode 100644 index 0000000..d9a2100 --- /dev/null +++ b/src/Maestro/Client/V0/Core/Pagination.hs @@ -0,0 +1,64 @@ +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE TypeOperators #-} + +module Maestro.Client.V0.Core.Pagination where + +import Data.Default.Class +import Data.Proxy (Proxy (..)) +import Servant.API (QueryParam, (:>)) +import Servant.Client.Core (Client, HasClient, clientWithRoute, + hoistClientMonad) + +-- | Pagination parameters +data Page = Page + { resultPerPage :: !Int -- ^ Total result per page + , pageNumber :: !Int -- ^ Page Number + } + +-- | maximum number of result +maxPageResult :: Int +maxPageResult = 100 + +instance Default Page where + def = Page maxPageResult 1 + +page :: Int -> Page +page n + | n >= 1 = Page maxPageResult n + | otherwise = error "Page number not in range [1..]" + +-- Utility for querying all results from a paged endpoint. +allPages :: (Monad m, Foldable t, Monoid (t a)) => (Page -> m (t a)) -> m (t a) +allPages act = fetch 1 + where + fetch pageNo = do + xs <- act $ Page maxPageResult pageNo + if length xs < maxPageResult then + pure xs + else do + next <- fetch $ pageNo + 1 + pure $ xs <> next -- Note: In case of list, concatenation takes linear time in the number of elements of the first list, thus, `xs` should come before. + +data Pagination + +type PaginationApi api = + QueryParam "count" Int + :> QueryParam "page" Int + :> api + +instance HasClient m api => HasClient m (Pagination :> api) where + type Client m (Pagination :> api) = Page -> Client m api + + clientWithRoute pm _ req Page{..} = + clientWithRoute + pm + (Proxy @(PaginationApi api)) + req + (Just resultPerPage) + (Just pageNumber) + + hoistClientMonad pm _pa hst subClient = hoistClientMonad pm (Proxy @api) hst . subClient diff --git a/src/Maestro/Client/V0/Datum.hs b/src/Maestro/Client/V0/Datum.hs index c52a6d6..02336ae 100644 --- a/src/Maestro/Client/V0/Datum.hs +++ b/src/Maestro/Client/V0/Datum.hs @@ -2,11 +2,11 @@ module Maestro.Client.V0.Datum ( getDatumByHash ) where -import Data.Text (Text) -import Maestro.API.V0 (_datum) +import Data.Text (Text) +import Maestro.API.V0 (_datum) import Maestro.API.V0.Datum -import Maestro.Client.Core import Maestro.Client.Env +import Maestro.Client.V0.Core import Maestro.Types.V0 import Servant.API.Generic import Servant.Client diff --git a/src/Maestro/Client/V0/Epochs.hs b/src/Maestro/Client/V0/Epochs.hs index bc53a39..6ab5639 100644 --- a/src/Maestro/Client/V0/Epochs.hs +++ b/src/Maestro/Client/V0/Epochs.hs @@ -5,8 +5,8 @@ module Maestro.Client.V0.Epochs import Maestro.API.V0 (_epochs) import Maestro.API.V0.Epochs -import Maestro.Client.Core import Maestro.Client.Env +import Maestro.Client.V0.Core import Maestro.Types.V0 import Servant.API.Generic import Servant.Client diff --git a/src/Maestro/Client/V0/General.hs b/src/Maestro/Client/V0/General.hs index 93350e8..18bc915 100644 --- a/src/Maestro/Client/V0/General.hs +++ b/src/Maestro/Client/V0/General.hs @@ -5,10 +5,10 @@ module Maestro.Client.V0.General , getProtocolParameters ) where -import Maestro.API.V0 (_general) +import Maestro.API.V0 (_general) import Maestro.API.V0.General -import Maestro.Client.Core import Maestro.Client.Env +import Maestro.Client.V0.Core import Maestro.Types.V0 import Servant.API.Generic import Servant.Client diff --git a/src/Maestro/Client/Core/Pagination.hs b/src/Maestro/Client/V0/Pagination.hs similarity index 97% rename from src/Maestro/Client/Core/Pagination.hs rename to src/Maestro/Client/V0/Pagination.hs index aeffc0f..2a572a1 100644 --- a/src/Maestro/Client/Core/Pagination.hs +++ b/src/Maestro/Client/V0/Pagination.hs @@ -5,7 +5,7 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} -module Maestro.Client.Core.Pagination where +module Maestro.Client.V0.Pagination where import Data.Default.Class import Data.Proxy (Proxy (..)) diff --git a/src/Maestro/Client/V0/Pools.hs b/src/Maestro/Client/V0/Pools.hs index dcf8251..841aafb 100644 --- a/src/Maestro/Client/V0/Pools.hs +++ b/src/Maestro/Client/V0/Pools.hs @@ -12,8 +12,8 @@ where import Maestro.API.V0 import Maestro.API.V0.Pool -import Maestro.Client.Core import Maestro.Client.Env +import Maestro.Client.V0.Core import Maestro.Types.V0 import Servant.API.Generic import Servant.Client diff --git a/src/Maestro/Client/V0/Scripts.hs b/src/Maestro/Client/V0/Scripts.hs index 2dd8bfe..c40641a 100644 --- a/src/Maestro/Client/V0/Scripts.hs +++ b/src/Maestro/Client/V0/Scripts.hs @@ -5,8 +5,8 @@ module Maestro.Client.V0.Scripts import Data.Text (Text) import Maestro.API.V0 (_scripts) import Maestro.API.V0.Scripts -import Maestro.Client.Core import Maestro.Client.Env +import Maestro.Client.V0.Core import Maestro.Types.V0 import Servant.API.Generic import Servant.Client diff --git a/src/Maestro/Client/V0/Transaction.hs b/src/Maestro/Client/V0/Transaction.hs index e62dfbd..641c561 100644 --- a/src/Maestro/Client/V0/Transaction.hs +++ b/src/Maestro/Client/V0/Transaction.hs @@ -10,8 +10,8 @@ import qualified Data.ByteString as BS import Data.Text (Text) import Maestro.API.V0 (_tx) import Maestro.API.V0.Transaction -import Maestro.Client.Core import Maestro.Client.Env +import Maestro.Client.V0.Core import Maestro.Types.V0 import Servant.API.Generic import Servant.Client diff --git a/src/Maestro/Client/V0/TxManager.hs b/src/Maestro/Client/V0/TxManager.hs index f3a9225..6776ed6 100644 --- a/src/Maestro/Client/V0/TxManager.hs +++ b/src/Maestro/Client/V0/TxManager.hs @@ -7,8 +7,8 @@ import qualified Data.ByteString as BS import Data.Text (Text) import Maestro.API.V0 (_txManager) import Maestro.API.V0.TxManager -import Maestro.Client.Core import Maestro.Client.Env +import Maestro.Client.V0.Core import Servant.API.Generic import Servant.Client From 51a761daad15d729dc714d25c6eb8134d2084309 Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Wed, 5 Jul 2023 20:19:13 +0530 Subject: [PATCH 05/24] Feat 30: Cursor based pagination --- maestro-sdk.cabal | 4 ++ src/Maestro/API/V1.hs | 14 ++++++ src/Maestro/Client/V1.hs | 10 ++++ src/Maestro/Client/V1/Core.hs | 19 +++++++ src/Maestro/Client/V1/Core/Pagination.hs | 63 ++++++++++++++++++++++++ 5 files changed, 110 insertions(+) create mode 100644 src/Maestro/API/V1.hs create mode 100644 src/Maestro/Client/V1.hs create mode 100644 src/Maestro/Client/V1/Core.hs create mode 100644 src/Maestro/Client/V1/Core/Pagination.hs diff --git a/maestro-sdk.cabal b/maestro-sdk.cabal index d87b4ae..6f091fc 100644 --- a/maestro-sdk.cabal +++ b/maestro-sdk.cabal @@ -26,6 +26,8 @@ common common DerivingStrategies DerivingVia GeneralisedNewtypeDeriving + FlexibleInstances + FlexibleContexts MultiParamTypeClasses NumericUnderscores OverloadedStrings @@ -33,6 +35,8 @@ common common RoleAnnotations ScopedTypeVariables TemplateHaskell + TypeApplications + TypeFamilies TypeOperators QuasiQuotes diff --git a/src/Maestro/API/V1.hs b/src/Maestro/API/V1.hs new file mode 100644 index 0000000..6a6c203 --- /dev/null +++ b/src/Maestro/API/V1.hs @@ -0,0 +1,14 @@ +module Maestro.API.V1 where + +import Data.Text (Text) +import Maestro.API.V0.General +import Servant.API +import Servant.API.Generic + +data MaestroApiV1 route = MaestroApiV1 + { _general :: route :- ToServantApi GeneralAPI + } deriving Generic + +newtype MaestroApiV1Auth route = MaestroApiV1Auth + { _apiV1 :: route :- Header' '[Required] "api-key" Text :> ToServantApi MaestroApiV1 } + deriving Generic diff --git a/src/Maestro/Client/V1.hs b/src/Maestro/Client/V1.hs new file mode 100644 index 0000000..83175a0 --- /dev/null +++ b/src/Maestro/Client/V1.hs @@ -0,0 +1,10 @@ +module Maestro.Client.V0 + ( module Maestro.Client.Env + , module Maestro.Client.Error + , module Maestro.Client.V0.Core + ) where + + +import Maestro.Client.Env +import Maestro.Client.Error +import Maestro.Client.V0.Core diff --git a/src/Maestro/Client/V1/Core.hs b/src/Maestro/Client/V1/Core.hs new file mode 100644 index 0000000..638e983 --- /dev/null +++ b/src/Maestro/Client/V1/Core.hs @@ -0,0 +1,19 @@ +module Maestro.Client.V1.Core + ( apiV1Client + , module Maestro.Client.V1.Core.Pagination + ) where + +import Control.Exception (throwIO) +import Maestro.API.V1 +import Maestro.Client.Env +import Maestro.Client.Error (fromServantClientError) +import Maestro.Client.V1.Core.Pagination +import Servant.API.Generic (fromServant) +import Servant.Client +import Servant.Client.Generic + +apiV1ClientAuth :: MaestroEnv -> MaestroApiV1Auth (AsClientT IO) +apiV1ClientAuth MaestroEnv{..} = genericClientHoist $ \x -> runClientM x _maeClientEnv >>= either (throwIO . fromServantClientError) pure + +apiV1Client :: MaestroEnv -> MaestroApiV1 (AsClientT IO) +apiV1Client mEnv@MaestroEnv {..} = fromServant $ _apiV1 (apiV1ClientAuth mEnv) _maeToken diff --git a/src/Maestro/Client/V1/Core/Pagination.hs b/src/Maestro/Client/V1/Core/Pagination.hs new file mode 100644 index 0000000..1e292c9 --- /dev/null +++ b/src/Maestro/Client/V1/Core/Pagination.hs @@ -0,0 +1,63 @@ +module Maestro.Client.V1.Core.Pagination where + +import Data.Default.Class +import Data.Kind (Type) +import Data.Maybe (isNothing) +import Data.Proxy (Proxy (..)) +import Data.Text (Text) +import Servant.API (QueryParam, (:>)) +import Servant.Client.Core (Client, HasClient, clientWithRoute, + hoistClientMonad) + +-- | Pagination parameters. +data Cursor = Cursor + { resultPerPage :: !Int -- ^ Total result to have per page. + , cursor :: !(Maybe Text) -- ^ Cursor. + } + +-- | Maximum number of result per page. +maxResultsPerPage :: Int +maxResultsPerPage = 100 + +instance Default Cursor where + def = Cursor maxResultsPerPage Nothing + +-- | Is the endpoint paged? +class (Monoid (CursorData a)) => HasCursor a where + type CursorData a :: Type + getNextCursor :: a -> Maybe Text + getCursorData :: a -> CursorData a + +-- Utility for querying all results from a paged endpoint. +allPages :: (Monad m, HasCursor a) => (Cursor -> m a) -> m (CursorData a) +allPages act = fetch Nothing + where + fetch cursor = do + xs <- act $ Cursor maxResultsPerPage cursor + let nextCursor = getNextCursor xs + cursorData = getCursorData xs + if isNothing nextCursor then + pure cursorData + else do + next <- fetch nextCursor + pure $ cursorData <> next -- Note: In case of list, concatenation takes linear time in the number of elements of the first list, thus, `cursorData` should come before. + +data Pagination + +type PaginationApi api = + QueryParam "count" Int + :> QueryParam "cursor" Text + :> api + +instance HasClient m api => HasClient m (Pagination :> api) where + type Client m (Pagination :> api) = Cursor -> Client m api + + clientWithRoute pm _ req Cursor {..} = + clientWithRoute + pm + (Proxy @(PaginationApi api)) + req + (Just resultPerPage) + cursor + + hoistClientMonad pm _pa hst subClient = hoistClientMonad pm (Proxy @api) hst . subClient From 9972c3da05efdb51b425880e556c7a90bb418bba Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Wed, 5 Jul 2023 20:30:15 +0530 Subject: [PATCH 06/24] Feat 30: Common to both versions separated --- maestro-sdk.cabal | 1 + src/Maestro/Types/Common.hs | 203 +++++++++++++++++++++++++++++++++ src/Maestro/Types/V0/Common.hs | 200 +------------------------------- src/Maestro/Types/V1/Common.hs | 3 +- 4 files changed, 209 insertions(+), 198 deletions(-) create mode 100644 src/Maestro/Types/Common.hs diff --git a/maestro-sdk.cabal b/maestro-sdk.cabal index 6f091fc..cd395f8 100644 --- a/maestro-sdk.cabal +++ b/maestro-sdk.cabal @@ -72,6 +72,7 @@ library Maestro.Client.V0.Transaction Maestro.Client.V0.TxManager + Maestro.Types.Common Maestro.Types.V0 Maestro.Types.V0.Accounts Maestro.Types.V0.Address diff --git a/src/Maestro/Types/Common.hs b/src/Maestro/Types/Common.hs new file mode 100644 index 0000000..09b06bb --- /dev/null +++ b/src/Maestro/Types/Common.hs @@ -0,0 +1,203 @@ +module Maestro.Types.Common + ( Tx, + TxIndex (..), + PolicyId (..), + AssetId (..), + CBORStream, + EpochNo (..), + EpochSize (..), + AbsoluteSlot (..), + SlotNo (..), + BlockHeight (..), + BlockHash (..), + TxHash (..), + Bech32StringOf (..), + HexStringOf, + HashStringOf (..), + DatumOptionType (..), + DatumOption (..), + ScriptType (..), + Script (..), + Asset (..), + TxCbor (..), + UtxoAddress (..), + Order (..), + LowerFirst, + ) +where + +import qualified Data.Aeson as Aeson +import qualified Data.ByteString as BS +import qualified Data.ByteString.Lazy as LBS +import Data.Char (toLower) +import Data.Default.Class +import Data.String (IsString) +import Data.Text (Text) +import qualified Data.Text as T +import Data.Word (Word64) +import Deriving.Aeson +import GHC.Natural (Natural) +import Servant.API + +-- | Phantom datatype to be used with constructors like `HashStringOf`. +data Tx + +-- | Index of UTxO in a transaction outputs. +newtype TxIndex = TxIndex Natural + deriving stock (Eq, Ord, Show, Generic) + deriving newtype (Num, Enum, Real, Integral, FromHttpApiData, ToHttpApiData, FromJSON, ToJSON) + +-- | Minting policy ID. +newtype PolicyId = PolicyId Text + deriving stock (Eq, Show, Generic) + deriving newtype (FromHttpApiData, ToHttpApiData, FromJSON, ToJSON, IsString) + +-- | Concatenation of hex encoded policy ID and hex encoded asset name. +newtype AssetId = AssetId Text + deriving stock (Eq, Ord, Show, Generic) + deriving newtype (FromHttpApiData, ToHttpApiData, FromJSON, ToJSON) + +-- | An epoch, i.e. the number of the epoch. +newtype EpochNo = EpochNo {unEpochNo :: Word64} + deriving stock (Eq, Ord, Show, Generic) + deriving newtype (Enum, Num, Real, Integral, ToJSON, FromJSON) + +instance ToHttpApiData EpochNo where + toQueryParam = T.pack . show . unEpochNo + +-- | Length of an epoch, i.e., number of slots in it. +newtype EpochSize = EpochSize {unEpochSize :: Word64} + deriving stock (Eq, Ord, Show, Generic) + deriving newtype (Enum, Num, Real, Integral, ToJSON, FromJSON) + +-- | Absolute Slot Number +newtype AbsoluteSlot = AbsoluteSlot {unAbsoluteSlot :: Natural} + deriving stock (Show, Eq, Generic) + deriving (FromJSON, ToJSON) + +-- | The 0-based index for the Ourboros time slot. +newtype SlotNo = SlotNo {unSlotNo :: Word64} + deriving stock (Eq, Ord, Show, Generic) + deriving newtype (Num, Bounded, Enum, Real, Integral, FromJSON, ToJSON) + +-- | Block Height +newtype BlockHeight = BlockHeight {unBlockHeight :: Natural} + deriving stock (Show, Eq, Ord, Generic) + deriving newtype (Num, Enum, Real, Integral, FromJSON, ToJSON) + +-- | Hash of the block. +newtype BlockHash = BlockHash {unBlockHash :: Text} + deriving stock (Show, Eq, Ord, Generic) + deriving (FromJSON, ToJSON) + +-- | Hash of the Transaction. +newtype TxHash = TxHash {unTxHash :: Text} + deriving stock (Show, Eq, Generic) + deriving newtype (IsString) + deriving (FromJSON, ToJSON) + +newtype Bech32StringOf a = Bech32StringOf Text + deriving stock (Eq, Show, Generic) + deriving newtype (FromHttpApiData, ToHttpApiData, FromJSON, ToJSON, IsString) + +type HexStringOf a = Text + +newtype HashStringOf a = HashStringOf Text + deriving stock (Eq, Show, Generic) + deriving newtype (FromHttpApiData, ToHttpApiData, FromJSON, ToJSON, IsString) + +data DatumOptionType = Inline | Hash + deriving stock (Show, Eq, Generic) + deriving (FromJSON, ToJSON) via CustomJSON '[ConstructorTagModifier '[LowerFirst]] DatumOptionType + +data DatumOption = DatumOption + { _datumOptionBytes :: !(Maybe Text), + _datumOptionHash :: !Text, + _datumOptionJson :: !(Maybe Aeson.Value), + _datumOptionType :: !DatumOptionType + } + deriving stock (Show, Eq, Generic) + deriving + (FromJSON, ToJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "_datumOption", LowerFirst]] DatumOption + +data ScriptType = Native | PlutusV1 | PlutusV2 + deriving stock (Show, Eq, Generic) + deriving + (FromJSON, ToJSON) + via CustomJSON '[ConstructorTagModifier '[LowerAll]] ScriptType + +data Script = Script + { _scriptBytes :: !(Maybe Text), + _scriptHash :: !Text, + _scriptJson :: !(Maybe Aeson.Value), + _scriptType :: !ScriptType + } + deriving stock (Show, Eq, Generic) + deriving + (FromJSON, ToJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "_script", LowerFirst]] Script + +data Asset = Asset + { _assetQuantity :: !Integer + , _assetUnit :: !Text + } + deriving stock (Show, Eq, Generic) + deriving + (FromJSON, ToJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "_asset", CamelToSnake]] Asset + +newtype TxCbor = TxCbor {_txCbor :: Text} + deriving stock (Show, Eq, Generic) + deriving + (FromJSON, ToJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "_tx", LowerFirst]] TxCbor + +newtype UtxoAddress = UtxoAddress {_utxoAddressAddress :: Text} + deriving stock (Show, Eq, Generic) + deriving + (FromJSON, ToJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "_utxoAddress", LowerFirst]] UtxoAddress + +data Order = Ascending | Descending + +instance ToHttpApiData Order where + toQueryParam Ascending = "asc" + toQueryParam Descending = "desc" + +instance Default Order where + def = Ascending + +instance Show Order where + show Ascending = "asc" + show Descending = "desc" + +data CBORStream + +instance Accept CBORStream where + contentType _ = "application/cbor" + +instance MimeRender CBORStream BS.ByteString where + mimeRender _ = LBS.fromStrict + +instance MimeRender CBORStream LBS.ByteString where + mimeRender _ = id + +instance MimeUnrender CBORStream BS.ByteString where + mimeUnrender _ = Right . LBS.toStrict + +instance MimeUnrender CBORStream LBS.ByteString where + mimeUnrender _ = Right + +-- | Will lower the first character for your type. +data LowerFirst + +instance StringModifier LowerFirst where + getStringModifier "" = "" + getStringModifier (c : cs) = toLower c : cs + +-- | Will lower all characters for your type. +data LowerAll + +instance StringModifier LowerAll where + getStringModifier cs = toLower <$> cs diff --git a/src/Maestro/Types/V0/Common.hs b/src/Maestro/Types/V0/Common.hs index 59ea986..38d3bea 100644 --- a/src/Maestro/Types/V0/Common.hs +++ b/src/Maestro/Types/V0/Common.hs @@ -1,152 +1,13 @@ module Maestro.Types.V0.Common - ( Tx, - TxIndex (..), - PolicyId (..), - AssetId (..), - CBORStream, - EpochNo (..), - EpochSize (..), - AbsoluteSlot (..), - SlotNo (..), - BlockHeight (..), - BlockHash (..), - TxHash (..), - Bech32StringOf (..), - HexStringOf, - HashStringOf (..), - DatumOptionType (..), - DatumOption (..), - ScriptType (..), - Script (..), - Asset (..), - Utxo (..), - TxCbor (..), - UtxoAddress (..), - Order (..), - LowerFirst, + ( Utxo (..), + module Maestro.Types.Common ) where -import qualified Data.Aeson as Aeson -import qualified Data.ByteString as BS -import qualified Data.ByteString.Lazy as LBS -import Data.Char (toLower) -import Data.Default.Class -import Data.String (IsString) import Data.Text (Text) -import qualified Data.Text as T -import Data.Word (Word64) import Deriving.Aeson import GHC.Natural (Natural) -import Servant.API - --- | Phantom datatype to be used with constructors like `HashStringOf`. -data Tx - --- | Index of UTxO in a transaction outputs. -newtype TxIndex = TxIndex Natural - deriving stock (Eq, Ord, Show, Generic) - deriving newtype (Num, Enum, Real, Integral, FromHttpApiData, ToHttpApiData, FromJSON, ToJSON) - --- | Minting policy ID. -newtype PolicyId = PolicyId Text - deriving stock (Eq, Show, Generic) - deriving newtype (FromHttpApiData, ToHttpApiData, FromJSON, ToJSON, IsString) - --- | Concatenation of hex encoded policy ID and hex encoded asset name. -newtype AssetId = AssetId Text - deriving stock (Eq, Ord, Show, Generic) - deriving newtype (FromHttpApiData, ToHttpApiData, FromJSON, ToJSON) - --- | An epoch, i.e. the number of the epoch. -newtype EpochNo = EpochNo {unEpochNo :: Word64} - deriving stock (Eq, Ord, Show, Generic) - deriving newtype (Enum, Num, Real, Integral, ToJSON, FromJSON) - -instance ToHttpApiData EpochNo where - toQueryParam = T.pack . show . unEpochNo - --- | Length of an epoch, i.e., number of slots in it. -newtype EpochSize = EpochSize {unEpochSize :: Word64} - deriving stock (Eq, Ord, Show, Generic) - deriving newtype (Enum, Num, Real, Integral, ToJSON, FromJSON) - --- | Absolute Slot Number -newtype AbsoluteSlot = AbsoluteSlot {unAbsoluteSlot :: Natural} - deriving stock (Show, Eq, Generic) - deriving (FromJSON, ToJSON) - --- | The 0-based index for the Ourboros time slot. -newtype SlotNo = SlotNo {unSlotNo :: Word64} - deriving stock (Eq, Ord, Show, Generic) - deriving newtype (Num, Bounded, Enum, Real, Integral, FromJSON, ToJSON) - --- | Block Height -newtype BlockHeight = BlockHeight {unBlockHeight :: Natural} - deriving stock (Show, Eq, Ord, Generic) - deriving newtype (Num, Enum, Real, Integral, FromJSON, ToJSON) - --- | Hash of the block. -newtype BlockHash = BlockHash {unBlockHash :: Text} - deriving stock (Show, Eq, Ord, Generic) - deriving (FromJSON, ToJSON) - --- | Hash of the Transaction. -newtype TxHash = TxHash {unTxHash :: Text} - deriving stock (Show, Eq, Generic) - deriving newtype (IsString) - deriving (FromJSON, ToJSON) - -newtype Bech32StringOf a = Bech32StringOf Text - deriving stock (Eq, Show, Generic) - deriving newtype (FromHttpApiData, ToHttpApiData, FromJSON, ToJSON, IsString) - -type HexStringOf a = Text - -newtype HashStringOf a = HashStringOf Text - deriving stock (Eq, Show, Generic) - deriving newtype (FromHttpApiData, ToHttpApiData, FromJSON, ToJSON, IsString) - -data DatumOptionType = Inline | Hash - deriving stock (Show, Eq, Generic) - deriving (FromJSON, ToJSON) via CustomJSON '[ConstructorTagModifier '[LowerFirst]] DatumOptionType - -data DatumOption = DatumOption - { _datumOptionBytes :: !(Maybe Text), - _datumOptionHash :: !Text, - _datumOptionJson :: !(Maybe Aeson.Value), - _datumOptionType :: !DatumOptionType - } - deriving stock (Show, Eq, Generic) - deriving - (FromJSON, ToJSON) - via CustomJSON '[FieldLabelModifier '[StripPrefix "_datumOption", LowerFirst]] DatumOption - -data ScriptType = Native | PlutusV1 | PlutusV2 - deriving stock (Show, Eq, Generic) - deriving - (FromJSON, ToJSON) - via CustomJSON '[ConstructorTagModifier '[LowerAll]] ScriptType - -data Script = Script - { _scriptBytes :: !(Maybe Text), - _scriptHash :: !Text, - _scriptJson :: !(Maybe Aeson.Value), - _scriptType :: !ScriptType - } - deriving stock (Show, Eq, Generic) - deriving - (FromJSON, ToJSON) - via CustomJSON '[FieldLabelModifier '[StripPrefix "_script", LowerFirst]] Script - -data Asset = Asset - { _assetQuantity :: !Integer - , _assetUnit :: !Text - } - deriving stock (Show, Eq, Generic) - deriving - (FromJSON, ToJSON) - via CustomJSON '[FieldLabelModifier '[StripPrefix "_asset", CamelToSnake]] Asset +import Maestro.Types.Common -- | Transaction output data Utxo = Utxo @@ -161,58 +22,3 @@ data Utxo = Utxo deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_utxo", CamelToSnake]] Utxo - -newtype TxCbor = TxCbor {_txCbor :: Text} - deriving stock (Show, Eq, Generic) - deriving - (FromJSON, ToJSON) - via CustomJSON '[FieldLabelModifier '[StripPrefix "_tx", LowerFirst]] TxCbor - -newtype UtxoAddress = UtxoAddress {_utxoAddressAddress :: Text} - deriving stock (Show, Eq, Generic) - deriving - (FromJSON, ToJSON) - via CustomJSON '[FieldLabelModifier '[StripPrefix "_utxoAddress", LowerFirst]] UtxoAddress - -data Order = Ascending | Descending - -instance ToHttpApiData Order where - toQueryParam Ascending = "asc" - toQueryParam Descending = "desc" - -instance Default Order where - def = Ascending - -instance Show Order where - show Ascending = "asc" - show Descending = "desc" - -data CBORStream - -instance Accept CBORStream where - contentType _ = "application/cbor" - -instance MimeRender CBORStream BS.ByteString where - mimeRender _ = LBS.fromStrict - -instance MimeRender CBORStream LBS.ByteString where - mimeRender _ = id - -instance MimeUnrender CBORStream BS.ByteString where - mimeUnrender _ = Right . LBS.toStrict - -instance MimeUnrender CBORStream LBS.ByteString where - mimeUnrender _ = Right - --- | Will lower the first character for your type. -data LowerFirst - -instance StringModifier LowerFirst where - getStringModifier "" = "" - getStringModifier (c : cs) = toLower c : cs - --- | Will lower all characters for your type. -data LowerAll - -instance StringModifier LowerAll where - getStringModifier cs = toLower <$> cs diff --git a/src/Maestro/Types/V1/Common.hs b/src/Maestro/Types/V1/Common.hs index 40efed6..82946f2 100644 --- a/src/Maestro/Types/V1/Common.hs +++ b/src/Maestro/Types/V1/Common.hs @@ -1,10 +1,11 @@ module Maestro.Types.V1.Common ( LastUpdated (..), + module Maestro.Types.Common ) where import Deriving.Aeson -import Maestro.Types.V0.Common +import Maestro.Types.Common -- | Details of the most recent block processed by the indexer (aka chain tip); that is, the data returned is correct as of this block in time. data LastUpdated = LastUpdated From 8a668d632e3e6371117edc4d6e333b9e284fa8c6 Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Wed, 5 Jul 2023 21:50:12 +0530 Subject: [PATCH 07/24] Feat 30: Pagination checked by querying UTxOs at multiple addresses --- maestro-exe/Maestro/Run/AddressV1.hs | 9 ++++++ maestro-exe/Main.hs | 7 +++- maestro-sdk.cabal | 15 ++++++++- src/Maestro/API/V1.hs | 6 ++-- src/Maestro/API/V1/Address.hs | 20 ++++++++++++ src/Maestro/Client/V1.hs | 8 +++-- src/Maestro/Client/V1/Address.hs | 28 ++++++++++++++++ src/Maestro/Types/Common.hs | 10 ------ src/Maestro/Types/V0/Common.hs | 15 +++++++-- src/Maestro/Types/V1.hs | 4 +-- src/Maestro/Types/V1/Common.hs | 48 ++++++++++++++++++++++++++++ src/Maestro/Types/V1/General.hs | 2 ++ 12 files changed, 150 insertions(+), 22 deletions(-) create mode 100644 maestro-exe/Maestro/Run/AddressV1.hs create mode 100644 src/Maestro/API/V1/Address.hs create mode 100644 src/Maestro/Client/V1/Address.hs diff --git a/maestro-exe/Maestro/Run/AddressV1.hs b/maestro-exe/Maestro/Run/AddressV1.hs new file mode 100644 index 0000000..8ae7b19 --- /dev/null +++ b/maestro-exe/Maestro/Run/AddressV1.hs @@ -0,0 +1,9 @@ +module Maestro.Run.AddressV1 where + +import Maestro.Client.V1 + +runV1AddressAPI :: MaestroEnv -> IO () +runV1AddressAPI mEnv = do + utxos <- allPages $ (flip $ utxosAtMultiAddresses mEnv Nothing Nothing) ["insert","your", "big", "address", "list", "here"] + putStrLn $ "Received: топ\n" ++ show utxos + -- writeFile "allUtxos.txt" $ show utxos diff --git a/maestro-exe/Main.hs b/maestro-exe/Main.hs index dd927a3..db2c952 100644 --- a/maestro-exe/Main.hs +++ b/maestro-exe/Main.hs @@ -1,13 +1,14 @@ module Main (main) where import qualified Data.Text as T -import Maestro.Client.V0 +import Maestro.Client.Env import Maestro.Run.Datum import Maestro.Run.Epochs import Maestro.Run.General import Maestro.Run.Pools import Maestro.Run.Scripts import Maestro.Run.Tx +import Maestro.Run.AddressV1 import System.Environment (getEnv) @@ -15,6 +16,7 @@ main :: IO () main = do apiKey <- maestroKey + apiKeyMain <- maestroMainKey env <- mkMaestroEnv (T.pack apiKey) Preprod V0 runPoolsAPI env runTxApi env @@ -22,6 +24,9 @@ main = do runDatumAPI env runScriptsAPI env runGeneralAPI env + env' <- mkMaestroEnv (T.pack apiKeyMain) Mainnet V1 + runV1AddressAPI env' where maestroKey = getEnv "MAESTRO_API_KEY" + maestroMainKey = getEnv "MAESTRO_MAIN_KEY" diff --git a/maestro-sdk.cabal b/maestro-sdk.cabal index cd395f8..67ef973 100644 --- a/maestro-sdk.cabal +++ b/maestro-sdk.cabal @@ -55,6 +55,10 @@ library Maestro.API.V0.Transaction Maestro.API.V0.TxManager + Maestro.API.V1 + Maestro.API.V1.Address + Maestro.API.V1.General + Maestro.Client.Env Maestro.Client.Error Maestro.Client.V0 @@ -66,12 +70,16 @@ library Maestro.Client.V0.Address Maestro.Client.V0.Assets Maestro.Client.V0.General - Maestro.Client.V0.Pagination Maestro.Client.V0.Pools Maestro.Client.V0.Scripts Maestro.Client.V0.Transaction Maestro.Client.V0.TxManager + Maestro.Client.V1 + Maestro.Client.V1.Core + Maestro.Client.V1.Core.Pagination + Maestro.Client.V1.Address + Maestro.Types.Common Maestro.Types.V0 Maestro.Types.V0.Accounts @@ -83,6 +91,10 @@ library Maestro.Types.V0.General Maestro.Types.V0.Pool + Maestro.Types.V1 + Maestro.Types.V1.Common + Maestro.Types.V1.General + -- other-modules: -- other-extensions: build-depends: @@ -142,6 +154,7 @@ executable maestro-exe Maestro.Run.Scripts Maestro.Run.Tx Maestro.Run.Epochs + Maestro.Run.AddressV1 -- other-extensions: hs-source-dirs: maestro-exe main-is: Main.hs diff --git a/src/Maestro/API/V1.hs b/src/Maestro/API/V1.hs index 6a6c203..d30784f 100644 --- a/src/Maestro/API/V1.hs +++ b/src/Maestro/API/V1.hs @@ -1,12 +1,14 @@ module Maestro.API.V1 where import Data.Text (Text) -import Maestro.API.V0.General +import Maestro.API.V1.Address +import Maestro.API.V1.General import Servant.API import Servant.API.Generic data MaestroApiV1 route = MaestroApiV1 - { _general :: route :- ToServantApi GeneralAPI + { _general :: route :- ToServantApi GeneralAPI + , _address :: route :- "addresses" :> ToServantApi AddressAPI } deriving Generic newtype MaestroApiV1Auth route = MaestroApiV1Auth diff --git a/src/Maestro/API/V1/Address.hs b/src/Maestro/API/V1/Address.hs new file mode 100644 index 0000000..0010530 --- /dev/null +++ b/src/Maestro/API/V1/Address.hs @@ -0,0 +1,20 @@ +module Maestro.API.V1.Address where + +import Data.Text (Text) +import Maestro.Client.V1.Core.Pagination +import Maestro.Types.V1 +import Servant.API +import Servant.API.Generic + +data AddressAPI route = AddressAPI + { + _addressesUtxos + :: route + :- "utxos" + :> QueryParam "resolve_datums" Bool + :> QueryParam "with_cbor" Bool + :> Pagination + :> ReqBody '[JSON] [Text] + :> Post '[JSON] Utxos + + } deriving (Generic) diff --git a/src/Maestro/Client/V1.hs b/src/Maestro/Client/V1.hs index 83175a0..561d9ee 100644 --- a/src/Maestro/Client/V1.hs +++ b/src/Maestro/Client/V1.hs @@ -1,10 +1,12 @@ -module Maestro.Client.V0 +module Maestro.Client.V1 ( module Maestro.Client.Env , module Maestro.Client.Error - , module Maestro.Client.V0.Core + , module Maestro.Client.V1.Core + , module Maestro.Client.V1.Address ) where import Maestro.Client.Env import Maestro.Client.Error -import Maestro.Client.V0.Core +import Maestro.Client.V1.Address +import Maestro.Client.V1.Core diff --git a/src/Maestro/Client/V1/Address.hs b/src/Maestro/Client/V1/Address.hs new file mode 100644 index 0000000..cd9a0c8 --- /dev/null +++ b/src/Maestro/Client/V1/Address.hs @@ -0,0 +1,28 @@ +module Maestro.Client.V1.Address where + +import Data.Text (Text) +import Maestro.API.V1 +import Maestro.API.V1.Address +import Maestro.Client.Env +import Maestro.Client.V1.Core +import Maestro.Types.V1 +import Servant.API.Generic +import Servant.Client + +addressClient :: MaestroEnv -> AddressAPI (AsClientT IO) +addressClient = fromServant . _address . apiV1Client + +-- | Returns list of utxos for multiple addresses +utxosAtMultiAddresses :: + -- | The Maestro Environment + MaestroEnv -> + -- | Query param to include the corresponding datums for datum hashes + Maybe Bool -> + -- | Query Param to include the CBOR encodings of the transaction outputs in the response + Maybe Bool -> + -- | The pagination attributes + Cursor -> + -- | List of Address in bech32 format to fetch utxo from + [Text] -> + IO Utxos +utxosAtMultiAddresses = _addressesUtxos . addressClient diff --git a/src/Maestro/Types/Common.hs b/src/Maestro/Types/Common.hs index 09b06bb..c8be6fa 100644 --- a/src/Maestro/Types/Common.hs +++ b/src/Maestro/Types/Common.hs @@ -18,7 +18,6 @@ module Maestro.Types.Common DatumOption (..), ScriptType (..), Script (..), - Asset (..), TxCbor (..), UtxoAddress (..), Order (..), @@ -138,15 +137,6 @@ data Script = Script (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_script", LowerFirst]] Script -data Asset = Asset - { _assetQuantity :: !Integer - , _assetUnit :: !Text - } - deriving stock (Show, Eq, Generic) - deriving - (FromJSON, ToJSON) - via CustomJSON '[FieldLabelModifier '[StripPrefix "_asset", CamelToSnake]] Asset - newtype TxCbor = TxCbor {_txCbor :: Text} deriving stock (Show, Eq, Generic) deriving diff --git a/src/Maestro/Types/V0/Common.hs b/src/Maestro/Types/V0/Common.hs index 38d3bea..646db5b 100644 --- a/src/Maestro/Types/V0/Common.hs +++ b/src/Maestro/Types/V0/Common.hs @@ -1,5 +1,6 @@ module Maestro.Types.V0.Common - ( Utxo (..), + ( Asset (..), + Utxo (..), module Maestro.Types.Common ) where @@ -9,7 +10,17 @@ import Deriving.Aeson import GHC.Natural (Natural) import Maestro.Types.Common --- | Transaction output +-- | Representation of asset in an UTxO. +data Asset = Asset + { _assetQuantity :: !Integer + , _assetUnit :: !Text + } + deriving stock (Show, Eq, Generic) + deriving + (FromJSON, ToJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "_asset", CamelToSnake]] Asset + +-- | Transaction output. data Utxo = Utxo { _utxoAddress :: !Text, _utxoAssets :: ![Asset], diff --git a/src/Maestro/Types/V1.hs b/src/Maestro/Types/V1.hs index ad43e58..ae3cb26 100644 --- a/src/Maestro/Types/V1.hs +++ b/src/Maestro/Types/V1.hs @@ -1,11 +1,9 @@ -- | Maestro types module Maestro.Types.V1 - ( module Maestro.Types.V0.Common - , module Maestro.Types.V1.Common + ( module Maestro.Types.V1.Common , module Maestro.Types.V1.General ) where -import Maestro.Types.V0.Common import Maestro.Types.V1.Common import Maestro.Types.V1.General diff --git a/src/Maestro/Types/V1/Common.hs b/src/Maestro/Types/V1/Common.hs index 82946f2..bcf117b 100644 --- a/src/Maestro/Types/V1/Common.hs +++ b/src/Maestro/Types/V1/Common.hs @@ -1,10 +1,16 @@ module Maestro.Types.V1.Common ( LastUpdated (..), + Asset (..), + UtxoData (..), + Utxos (..), module Maestro.Types.Common ) where +import Data.Text (Text) import Deriving.Aeson +import GHC.Natural (Natural) +import Maestro.Client.V1.Core.Pagination (HasCursor (..)) import Maestro.Types.Common -- | Details of the most recent block processed by the indexer (aka chain tip); that is, the data returned is correct as of this block in time. @@ -16,3 +22,45 @@ data LastUpdated = LastUpdated } deriving stock (Eq, Ord, Show, Generic) deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_lastUpdated", CamelToSnake]] LastUpdated + +-- | Representation of asset in an UTxO. +data Asset = Asset + { _assetAmount :: !Integer + , _assetUnit :: !Text + } + deriving stock (Show, Eq, Generic) + deriving + (FromJSON, ToJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "_asset", CamelToSnake]] Asset + +-- | Transaction output. +data UtxoData = UtxoData + { _utxoDataAddress :: !Text, + _utxoDataAssets :: ![Asset], + _utxoDataDatum :: !(Maybe DatumOption), + _utxoDataIndex :: !Natural, + _utxoDataReferenceScript :: !(Maybe Script), + _utxoDataTxHash :: !Text, + _utxoDataSlot :: !SlotNo, + _utxoDataTxoutCbor :: !(Maybe TxCbor) + } + deriving stock (Show, Eq, Generic) + deriving + (FromJSON, ToJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "_utxoData", CamelToSnake]] UtxoData + +-- | Transaction Outputs +data Utxos = Utxos + { _utxosData :: ![UtxoData], + _utxosLastUpdated :: !LastUpdated, + _utxosNextCursor :: !(Maybe Text) + } + deriving stock (Show, Eq, Generic) + deriving + (FromJSON, ToJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "_utxos", CamelToSnake]] Utxos + +instance HasCursor Utxos where + type CursorData Utxos = [UtxoData] + getNextCursor utxos = _utxosNextCursor utxos + getCursorData utxos = _utxosData utxos diff --git a/src/Maestro/Types/V1/General.hs b/src/Maestro/Types/V1/General.hs index 285a670..4099dd4 100644 --- a/src/Maestro/Types/V1/General.hs +++ b/src/Maestro/Types/V1/General.hs @@ -181,6 +181,8 @@ data ProtocolParameters = ProtocolParameters { _protocolParametersData :: !ProtocolParametersData , _protocolParametersLastUpdated :: !LastUpdated } + deriving stock (Eq, Show, Generic) + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_protocolParameters", CamelToSnake]] ProtocolParameters -- | Protocol parameters for the latest epoch. data ProtocolParametersData = ProtocolParametersData From c598820c4f05c9e77da82bbe69266ee539befdc3 Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Thu, 6 Jul 2023 13:45:08 +0530 Subject: [PATCH 08/24] Feat 30: V1 Endpoints support - Singleton type for api versions for added type safety --- README.md | 4 +-- maestro-exe/Maestro/Run/Address.hs | 8 ++++++ maestro-exe/Maestro/Run/AddressV1.hs | 9 ------- maestro-exe/Maestro/Run/Datum.hs | 2 +- maestro-exe/Maestro/Run/Epochs.hs | 2 +- maestro-exe/Maestro/Run/General.hs | 2 +- maestro-exe/Maestro/Run/Pools.hs | 18 ++++++------- maestro-exe/Maestro/Run/Scripts.hs | 2 +- maestro-exe/Maestro/Run/Tx.hs | 8 +++--- maestro-exe/Main.hs | 9 ++++--- maestro-sdk.cabal | 3 ++- src/Maestro/Client/Env.hs | 39 +++++++++++++++++++--------- src/Maestro/Client/V0/Accounts.hs | 14 +++++----- src/Maestro/Client/V0/Address.hs | 10 +++---- src/Maestro/Client/V0/Assets.hs | 20 +++++++------- src/Maestro/Client/V0/Core.hs | 6 ++--- src/Maestro/Client/V0/Datum.hs | 4 +-- src/Maestro/Client/V0/Epochs.hs | 6 ++--- src/Maestro/Client/V0/General.hs | 10 +++---- src/Maestro/Client/V0/Pools.hs | 18 ++++++------- src/Maestro/Client/V0/Scripts.hs | 4 +-- src/Maestro/Client/V0/Transaction.hs | 12 ++++----- src/Maestro/Client/V0/TxManager.hs | 4 +-- src/Maestro/Client/V1/Address.hs | 4 +-- src/Maestro/Client/V1/Core.hs | 4 +-- 25 files changed, 119 insertions(+), 103 deletions(-) create mode 100644 maestro-exe/Maestro/Run/Address.hs delete mode 100644 maestro-exe/Maestro/Run/AddressV1.hs diff --git a/README.md b/README.md index 7aaf524..841e1ba 100644 --- a/README.md +++ b/README.md @@ -36,8 +36,8 @@ ```haskell import Maestro.Client.Env -myEnvPreprod <- mkMaestroEnv "Your-API-Key" Preprod -myEnvMainnet <- mkMaestroEnv "Your-API-Key" Mainnet +myEnvPreprod <- mkMaestroEnv @'V0 "Your-API-Key" Preprod +myEnvMainnet <- mkMaestroEnv @'V0 "Your-API-Key" Mainnet ``` 4. Example: chain tip ```haskell diff --git a/maestro-exe/Maestro/Run/Address.hs b/maestro-exe/Maestro/Run/Address.hs new file mode 100644 index 0000000..5fa3234 --- /dev/null +++ b/maestro-exe/Maestro/Run/Address.hs @@ -0,0 +1,8 @@ +module Maestro.Run.Address where + +import Maestro.Client.Env +import qualified Maestro.Client.V0 as V0 +import qualified Maestro.Client.V1 as V1 + +runAddressAPI :: MaestroEnv 'V0 -> IO () +runAddressAPI mEnv = undefined diff --git a/maestro-exe/Maestro/Run/AddressV1.hs b/maestro-exe/Maestro/Run/AddressV1.hs deleted file mode 100644 index 8ae7b19..0000000 --- a/maestro-exe/Maestro/Run/AddressV1.hs +++ /dev/null @@ -1,9 +0,0 @@ -module Maestro.Run.AddressV1 where - -import Maestro.Client.V1 - -runV1AddressAPI :: MaestroEnv -> IO () -runV1AddressAPI mEnv = do - utxos <- allPages $ (flip $ utxosAtMultiAddresses mEnv Nothing Nothing) ["insert","your", "big", "address", "list", "here"] - putStrLn $ "Received: топ\n" ++ show utxos - -- writeFile "allUtxos.txt" $ show utxos diff --git a/maestro-exe/Maestro/Run/Datum.hs b/maestro-exe/Maestro/Run/Datum.hs index e07134e..acdb9c7 100644 --- a/maestro-exe/Maestro/Run/Datum.hs +++ b/maestro-exe/Maestro/Run/Datum.hs @@ -3,7 +3,7 @@ module Maestro.Run.Datum where import Maestro.Client.V0 import Text.Printf (printf) -runDatumAPI :: MaestroEnv -> IO () +runDatumAPI :: MaestroEnv 'V0 -> IO () runDatumAPI mEnv = do let datumHash = "938dc15a5faa3da8e7f1e3ed8ca50b49248f8fffdfc04ff3cf7dffa0d06343eb" -- Quiet an involved datum. printf "Fetching datum from hash %s...\n" datumHash diff --git a/maestro-exe/Maestro/Run/Epochs.hs b/maestro-exe/Maestro/Run/Epochs.hs index 67a7d5b..535a0b2 100644 --- a/maestro-exe/Maestro/Run/Epochs.hs +++ b/maestro-exe/Maestro/Run/Epochs.hs @@ -2,7 +2,7 @@ module Maestro.Run.Epochs where import Maestro.Client.V0 -runEpochsAPI :: MaestroEnv -> IO () +runEpochsAPI :: MaestroEnv 'V0 -> IO () runEpochsAPI mEnv = do putStrLn "Fetching Current Epoch's Info ..." currentEpochInfo <- getCurrentEpoch mEnv diff --git a/maestro-exe/Maestro/Run/General.hs b/maestro-exe/Maestro/Run/General.hs index 1d29e89..774eb31 100644 --- a/maestro-exe/Maestro/Run/General.hs +++ b/maestro-exe/Maestro/Run/General.hs @@ -3,7 +3,7 @@ module Maestro.Run.General where import Maestro.Client.V0 import Text.Printf (printf) -runGeneralAPI :: MaestroEnv -> IO () +runGeneralAPI :: MaestroEnv 'V0 -> IO () runGeneralAPI mEnv = do chainTip <- getChainTip mEnv printf "Querying chain-tip, received: топ\n%s\n" (show chainTip) diff --git a/maestro-exe/Maestro/Run/Pools.hs b/maestro-exe/Maestro/Run/Pools.hs index 0bb8ae7..b97564d 100644 --- a/maestro-exe/Maestro/Run/Pools.hs +++ b/maestro-exe/Maestro/Run/Pools.hs @@ -6,7 +6,7 @@ import Maestro.Types.V0 poolId :: Bech32StringOf PoolId poolId = "pool1rkfs9glmfva3jd0q9vnlqvuhnrflpzj4l07u6sayfx5k7d788us" -runPoolsAPI :: MaestroEnv -> IO () +runPoolsAPI :: MaestroEnv 'V0 -> IO () runPoolsAPI mEnv = do putStrLn "Fetching List Pools ..." lstPools <- runListPools mEnv @@ -40,26 +40,26 @@ runPoolsAPI mEnv = do updates <- runPoolInfo mEnv putStrLn $ "fetched pool Updates: \n " ++ show updates -runPoolUpdates :: MaestroEnv -> IO [PoolUpdate] +runPoolUpdates :: MaestroEnv 'V0 -> IO [PoolUpdate] runPoolUpdates mEnv = poolUpdates mEnv poolId -runListPools :: MaestroEnv -> IO [PoolListInfo] +runListPools :: MaestroEnv 'V0 -> IO [PoolListInfo] runListPools mEnv = listPools mEnv (Page 1 1) -runPoolBlocks :: MaestroEnv -> IO [PoolBlock] +runPoolBlocks :: MaestroEnv 'V0 -> IO [PoolBlock] runPoolBlocks mEnv = poolBlocks mEnv poolId (Page 1 1) Nothing (Just Ascending) -runPoolDelegators :: MaestroEnv -> IO [DelegatorInfo] +runPoolDelegators :: MaestroEnv 'V0 -> IO [DelegatorInfo] runPoolDelegators mEnv = poolDelegators mEnv poolId (Page 1 1) -runPoolHistory :: MaestroEnv -> IO [PoolHistory] +runPoolHistory :: MaestroEnv 'V0 -> IO [PoolHistory] runPoolHistory mEnv = poolHistory mEnv poolId (Page 1 1) Nothing (Just Ascending) -runPoolInfo :: MaestroEnv -> IO PoolInfo +runPoolInfo :: MaestroEnv 'V0 -> IO PoolInfo runPoolInfo mEnv = poolInfo mEnv poolId -runPoolMetadata :: MaestroEnv -> IO PoolMetadata +runPoolMetadata :: MaestroEnv 'V0 -> IO PoolMetadata runPoolMetadata mEnv = poolMetadata mEnv poolId -runPoolRelay :: MaestroEnv -> IO [PoolRelay] +runPoolRelay :: MaestroEnv 'V0 -> IO [PoolRelay] runPoolRelay mEnv = poolRelays mEnv poolId diff --git a/maestro-exe/Maestro/Run/Scripts.hs b/maestro-exe/Maestro/Run/Scripts.hs index f51e30d..afdd6d2 100644 --- a/maestro-exe/Maestro/Run/Scripts.hs +++ b/maestro-exe/Maestro/Run/Scripts.hs @@ -3,7 +3,7 @@ module Maestro.Run.Scripts where import Maestro.Client.V0 import Text.Printf (printf) -runScriptsAPI :: MaestroEnv -> IO () +runScriptsAPI :: MaestroEnv 'V0 -> IO () runScriptsAPI mEnv = do let scriptHash = "3a888d65f16790950a72daee1f63aa05add6d268434107cfa5b67712" printf "Fetching script from hash %s...\n" scriptHash diff --git a/maestro-exe/Maestro/Run/Tx.hs b/maestro-exe/Maestro/Run/Tx.hs index 963f1a7..0e3899d 100644 --- a/maestro-exe/Maestro/Run/Tx.hs +++ b/maestro-exe/Maestro/Run/Tx.hs @@ -6,7 +6,7 @@ import Maestro.Types.V0 txHash :: HashStringOf Tx txHash = "7fdf7a20ba50d841344ab0cb368da6a047ce1e2a29b707586f61f0b8fea6bcf2" -runTxApi :: MaestroEnv -> IO () +runTxApi :: MaestroEnv 'V0 -> IO () runTxApi mEnv = do putStrLn "Fetching Tx Address ..." txAddr <- runTxAddress mEnv @@ -20,11 +20,11 @@ runTxApi mEnv = do utxo <- runTxUtxo mEnv putStrLn $ "fetched Tx Utxos: \n " ++ show utxo -runTxAddress :: MaestroEnv -> IO UtxoAddress +runTxAddress :: MaestroEnv 'V0 -> IO UtxoAddress runTxAddress mEnv = txAddress mEnv txHash $ TxIndex 0 -runTxCbor :: MaestroEnv -> IO TxCbor +runTxCbor :: MaestroEnv 'V0 -> IO TxCbor runTxCbor mEnv = txCbor mEnv txHash -runTxUtxo :: MaestroEnv -> IO Utxo +runTxUtxo :: MaestroEnv 'V0 -> IO Utxo runTxUtxo mEnv = txUtxo mEnv txHash (TxIndex 0) (Just True) (Just True) diff --git a/maestro-exe/Main.hs b/maestro-exe/Main.hs index db2c952..11b8f3c 100644 --- a/maestro-exe/Main.hs +++ b/maestro-exe/Main.hs @@ -2,13 +2,13 @@ module Main (main) where import qualified Data.Text as T import Maestro.Client.Env +import Maestro.Run.Address import Maestro.Run.Datum import Maestro.Run.Epochs import Maestro.Run.General import Maestro.Run.Pools import Maestro.Run.Scripts import Maestro.Run.Tx -import Maestro.Run.AddressV1 import System.Environment (getEnv) @@ -17,15 +17,16 @@ main :: IO () main = do apiKey <- maestroKey apiKeyMain <- maestroMainKey - env <- mkMaestroEnv (T.pack apiKey) Preprod V0 + env <- mkMaestroEnv @'V0 (T.pack apiKey) Preprod runPoolsAPI env runTxApi env runEpochsAPI env runDatumAPI env runScriptsAPI env runGeneralAPI env - env' <- mkMaestroEnv (T.pack apiKeyMain) Mainnet V1 - runV1AddressAPI env' + -- env' <- mkMaestroEnv @'V1 (T.pack apiKeyMain) Mainnet + env' <- mkMaestroEnv @'V0 (T.pack apiKeyMain) Mainnet + runAddressAPI env' where maestroKey = getEnv "MAESTRO_API_KEY" diff --git a/maestro-sdk.cabal b/maestro-sdk.cabal index 67ef973..23d4ba6 100644 --- a/maestro-sdk.cabal +++ b/maestro-sdk.cabal @@ -21,6 +21,7 @@ source-repository head common common ghc-options: -Wall default-extensions: + GADTs DataKinds DeriveGeneric DerivingStrategies @@ -154,7 +155,7 @@ executable maestro-exe Maestro.Run.Scripts Maestro.Run.Tx Maestro.Run.Epochs - Maestro.Run.AddressV1 + Maestro.Run.Address -- other-extensions: hs-source-dirs: maestro-exe main-is: Main.hs diff --git a/src/Maestro/Client/Env.hs b/src/Maestro/Client/Env.hs index 601e48b..6b15c7f 100644 --- a/src/Maestro/Client/Env.hs +++ b/src/Maestro/Client/Env.hs @@ -14,25 +14,40 @@ import qualified Servant.Client as Servant type MaestroToken = Text -data MaestroEnv = MaestroEnv +data MaestroApiVersion = V0 | V1 + +instance Show MaestroApiVersion where + show V0 = "v0" + show V1 = "v1" + +data SingMaestroApiVersion (v :: MaestroApiVersion) where + SingV0 :: SingMaestroApiVersion 'V0 + SingV1 :: SingMaestroApiVersion 'V1 + +fromSingMaestroApiVersion :: SingMaestroApiVersion v -> MaestroApiVersion +fromSingMaestroApiVersion SingV0 = V0 +fromSingMaestroApiVersion SingV1 = V1 + +class SingMaestroApiVersionI (v :: MaestroApiVersion) + where singMaestroApiVersion :: SingMaestroApiVersion v + +instance SingMaestroApiVersionI 'V0 where singMaestroApiVersion = SingV0 +instance SingMaestroApiVersionI 'V1 where singMaestroApiVersion = SingV1 + +data MaestroEnv (v :: MaestroApiVersion) = MaestroEnv { _maeClientEnv :: !Servant.ClientEnv , _maeToken :: !MaestroToken } data MaestroNetwork = Mainnet | Preprod -data MaestroApiVersion = V0 | V1 - --- TODO : Move version check inside. maestroBaseUrl :: MaestroNetwork -> MaestroApiVersion -> String -maestroBaseUrl Preprod V0 = "https://preprod.gomaestro-api.org/v0" -maestroBaseUrl Preprod V1 = "https://preprod.gomaestro-api.org/v1" -maestroBaseUrl Mainnet V0 = "https://mainnet.gomaestro-api.org/v0" -maestroBaseUrl Mainnet V1 = "https://mainnet.gomaestro-api.org/v1" - -mkMaestroEnv :: MaestroToken -> MaestroNetwork -> MaestroApiVersion -> IO MaestroEnv -mkMaestroEnv token nid apiVersion = do - clientEnv <- servantClientEnv $ maestroBaseUrl nid apiVersion +maestroBaseUrl Preprod v = "https://preprod.gomaestro-api.org/" <> show v +maestroBaseUrl Mainnet v = "https://mainnet.gomaestro-api.org/" <> show v + +mkMaestroEnv :: forall (apiVersion :: MaestroApiVersion). SingMaestroApiVersionI apiVersion => MaestroToken -> MaestroNetwork -> IO (MaestroEnv apiVersion) +mkMaestroEnv token nid = do + clientEnv <- servantClientEnv $ maestroBaseUrl nid (fromSingMaestroApiVersion $ singMaestroApiVersion @apiVersion) pure $ MaestroEnv { _maeClientEnv = clientEnv, _maeToken = token } servantClientEnv :: String -> IO Servant.ClientEnv diff --git a/src/Maestro/Client/V0/Accounts.hs b/src/Maestro/Client/V0/Accounts.hs index 89f11e5..bf40793 100644 --- a/src/Maestro/Client/V0/Accounts.hs +++ b/src/Maestro/Client/V0/Accounts.hs @@ -9,23 +9,23 @@ import Maestro.Types.V0 import Servant.API.Generic import Servant.Client -accountsClient :: MaestroEnv -> AccountsAPI (AsClientT IO) +accountsClient :: MaestroEnv 'V0 -> AccountsAPI (AsClientT IO) accountsClient = fromServant . _accounts . apiV0Client -getAccount :: MaestroEnv -> Text -> IO AccountInfo +getAccount :: MaestroEnv 'V0 -> Text -> IO AccountInfo getAccount = _account . accountsClient -listAccountAddresses :: MaestroEnv -> Text -> Page -> IO [Text] +listAccountAddresses :: MaestroEnv 'V0 -> Text -> Page -> IO [Text] listAccountAddresses = _accountAddresses . accountsClient -listAccountAssets :: MaestroEnv -> Text -> Page -> IO [Asset] +listAccountAssets :: MaestroEnv 'V0 -> Text -> Page -> IO [Asset] listAccountAssets = _accountAssets . accountsClient -listAccountHistory :: MaestroEnv -> Text -> Maybe EpochNo -> Page -> IO [AccountHistory] +listAccountHistory :: MaestroEnv 'V0 -> Text -> Maybe EpochNo -> Page -> IO [AccountHistory] listAccountHistory = _accountsHistory . accountsClient -listAccountRewards :: MaestroEnv -> Text -> Page -> IO [AccountReward] +listAccountRewards :: MaestroEnv 'V0 -> Text -> Page -> IO [AccountReward] listAccountRewards = _accountsReward . accountsClient -listAccountUpdates :: MaestroEnv -> Text -> Page -> IO [AccountUpdate] +listAccountUpdates :: MaestroEnv 'V0 -> Text -> Page -> IO [AccountUpdate] listAccountUpdates = _accountsUpdates . accountsClient diff --git a/src/Maestro/Client/V0/Address.hs b/src/Maestro/Client/V0/Address.hs index 5ec9fef..926d29e 100644 --- a/src/Maestro/Client/V0/Address.hs +++ b/src/Maestro/Client/V0/Address.hs @@ -9,14 +9,14 @@ import Maestro.Types.V0 import Servant.API.Generic import Servant.Client -addressClient :: MaestroEnv -> AddressAPI (AsClientT IO) +addressClient :: MaestroEnv 'V0 -> AddressAPI (AsClientT IO) addressClient = fromServant . _address . apiV0Client -- | -- Returns list of utxos for multiple addresses utxosAtMultiAddresses :: -- | The Maestro Environment - MaestroEnv -> + MaestroEnv 'V0 -> -- | Query param to include the corresponding datums for datum hashes Maybe Bool -> -- | Query Param to include the CBOR encodings of the transaction outputs in the response @@ -31,7 +31,7 @@ utxosAtMultiAddresses = _addressesUtxos . addressClient -- | -- Returns list of utxo for specific address utxosAtAddress :: - MaestroEnv -> + MaestroEnv 'V0 -> -- | The Address in bech32 format Text -> -- | Query param to include the corresponding datums for datum hashes @@ -46,7 +46,7 @@ utxosAtAddress = _addressUtxo . addressClient -- | -- Returns list of utxo ref for address getRefsAtAddress :: - MaestroEnv -> + MaestroEnv 'V0 -> -- | The Address in bech32 format Text -> -- | The pagination attributes @@ -57,7 +57,7 @@ getRefsAtAddress = _addressUtxoRefs . addressClient -- | -- Get the transaction count for an address getTxCountForAddress :: - MaestroEnv -> + MaestroEnv 'V0 -> -- | The Address in bech32 format Text -> IO [AddressTxCount] diff --git a/src/Maestro/Client/V0/Assets.hs b/src/Maestro/Client/V0/Assets.hs index 85e4233..44af505 100644 --- a/src/Maestro/Client/V0/Assets.hs +++ b/src/Maestro/Client/V0/Assets.hs @@ -9,14 +9,14 @@ import Maestro.Types.V0 import Servant.API.Generic import Servant.Client -assetClient :: MaestroEnv -> AssetsAPI (AsClientT IO) +assetClient :: MaestroEnv 'V0 -> AssetsAPI (AsClientT IO) assetClient = fromServant . _assets . apiV0Client -- | -- Returns list of Information about the assets of the given policy ID listAssetInfoByPolicyId :: -- | The Maestro Environment - MaestroEnv -> + MaestroEnv 'V0 -> -- | The Hex encoded policy ID PolicyId -> -- | Pagination @@ -28,7 +28,7 @@ listAssetInfoByPolicyId = _assetPolicyInfo . assetClient -- Returns a list of addresses which holding some of an asset of the given policy ID listAssetAddressByPolicyId :: -- | The Maestro Environment - MaestroEnv -> + MaestroEnv 'V0 -> -- | The Hex encoded policy ID PolicyId -> -- | Pagination @@ -40,7 +40,7 @@ listAssetAddressByPolicyId = _assetPolicyAddress . assetClient -- Returns list of transactions in which an address receives an asset of the specified policy listTxByPolicyId :: -- | The Maestro Environment - MaestroEnv -> + MaestroEnv 'V0 -> -- | The Hex encoded policy ID PolicyId -> -- | Pagination @@ -52,7 +52,7 @@ listTxByPolicyId = _assetPolicyTxs . assetClient -- Returns UTxOs which contain assets of the given policy ID, with the asset names and amounts listUtxosByPolicyId :: -- | The Maestro Environment - MaestroEnv -> + MaestroEnv 'V0 -> -- | The Hex encoded policy ID PolicyId -> -- | Pagination @@ -64,7 +64,7 @@ listUtxosByPolicyId = _assetPolicyUtxos . assetClient -- Returns UTxOs which contain assets of the given policy ID, with the asset names and amounts getAssetDetail :: -- | The Maestro Environment - MaestroEnv -> + MaestroEnv 'V0 -> -- | Asset, encoded as concatenation of hex of policy ID and asset name AssetId -> IO AssetInfo @@ -74,7 +74,7 @@ getAssetDetail = _assetDetail . assetClient -- Returns a list of addresses which hold some amount of the specified asset listAssetAddresses :: -- | The Maestro Environment - MaestroEnv -> + MaestroEnv 'V0 -> -- | Asset, encoded as concatenation of hex of policy ID and asset name AssetId -> Page -> @@ -85,7 +85,7 @@ listAssetAddresses = _assetAddresses . assetClient -- Returns list of transactions in which an address receives an asset of the specified policy listAssetTx :: -- | The Maestro Environment - MaestroEnv -> + MaestroEnv 'V0 -> -- | Asset, encoded as concatenation of hex of policy ID and asset name AssetId -> -- | Return only transactions after supplied block height @@ -100,7 +100,7 @@ listAssetTx = _assetTxs . assetClient -- Returns list of transactions which minted or burned the specified asset listAssetUpdates :: -- | The Maestro Environment - MaestroEnv -> + MaestroEnv 'V0 -> -- | Asset, encoded as concatenation of hex of policy ID and asset name AssetId -> -- | The Pagination @@ -114,7 +114,7 @@ listAssetUpdates = _assetUpdates . assetClient -- Returns UTxOs containing the specified asset, each paired with the amount of the asset listAssetUtxos :: -- | The Maestro Environment - MaestroEnv -> + MaestroEnv 'V0 -> -- | Asset, encoded as concatenation of hex of policy ID and asset name AssetId -> -- | The Pagination diff --git a/src/Maestro/Client/V0/Core.hs b/src/Maestro/Client/V0/Core.hs index 1acd9ad..621ca52 100644 --- a/src/Maestro/Client/V0/Core.hs +++ b/src/Maestro/Client/V0/Core.hs @@ -13,8 +13,8 @@ import Servant.Client import Servant.Client.Generic -apiV0ClientAuth :: MaestroEnv -> MaestroApiV0Auth (AsClientT IO) -apiV0ClientAuth MaestroEnv{..} = genericClientHoist $ \x -> runClientM x _maeClientEnv >>= either (throwIO . fromServantClientError) pure +apiV0ClientAuth :: MaestroEnv 'V0 -> MaestroApiV0Auth (AsClientT IO) +apiV0ClientAuth MaestroEnv {..} = genericClientHoist $ \x -> runClientM x _maeClientEnv >>= either (throwIO . fromServantClientError) pure -apiV0Client :: MaestroEnv -> MaestroApiV0 (AsClientT IO) +apiV0Client :: MaestroEnv 'V0 -> MaestroApiV0 (AsClientT IO) apiV0Client mEnv@MaestroEnv {..} = fromServant $ _apiV0 (apiV0ClientAuth mEnv) _maeToken diff --git a/src/Maestro/Client/V0/Datum.hs b/src/Maestro/Client/V0/Datum.hs index 02336ae..90c002d 100644 --- a/src/Maestro/Client/V0/Datum.hs +++ b/src/Maestro/Client/V0/Datum.hs @@ -11,9 +11,9 @@ import Maestro.Types.V0 import Servant.API.Generic import Servant.Client -datumClient :: MaestroEnv -> DatumAPI (AsClientT IO) +datumClient :: MaestroEnv 'V0 -> DatumAPI (AsClientT IO) datumClient = fromServant . _datum . apiV0Client -- | Get information about the datum from it's hash. -getDatumByHash :: MaestroEnv -> Text -> IO Datum +getDatumByHash :: MaestroEnv 'V0 -> Text -> IO Datum getDatumByHash = _datumByHash . datumClient diff --git a/src/Maestro/Client/V0/Epochs.hs b/src/Maestro/Client/V0/Epochs.hs index 6ab5639..347aaf1 100644 --- a/src/Maestro/Client/V0/Epochs.hs +++ b/src/Maestro/Client/V0/Epochs.hs @@ -11,13 +11,13 @@ import Maestro.Types.V0 import Servant.API.Generic import Servant.Client -epochsClient :: MaestroEnv -> EpochsAPI (AsClientT IO) +epochsClient :: MaestroEnv 'V0 -> EpochsAPI (AsClientT IO) epochsClient = fromServant . _epochs . apiV0Client -- | Get information about the current epoch. -getCurrentEpoch :: MaestroEnv -> IO CurrentEpochInfo +getCurrentEpoch :: MaestroEnv 'V0 -> IO CurrentEpochInfo getCurrentEpoch = _currentEpochInfo . epochsClient -- | Get information about a specific epoch. -getEpochInfo :: MaestroEnv -> EpochNo -> IO EpochInfo +getEpochInfo :: MaestroEnv 'V0 -> EpochNo -> IO EpochInfo getEpochInfo = _epochInfo . epochsClient diff --git a/src/Maestro/Client/V0/General.hs b/src/Maestro/Client/V0/General.hs index 18bc915..dfb280c 100644 --- a/src/Maestro/Client/V0/General.hs +++ b/src/Maestro/Client/V0/General.hs @@ -13,21 +13,21 @@ import Maestro.Types.V0 import Servant.API.Generic import Servant.Client -generalClient :: MaestroEnv -> GeneralAPI (AsClientT IO) +generalClient :: MaestroEnv 'V0 -> GeneralAPI (AsClientT IO) generalClient = fromServant . _general . apiV0Client -- | Get details about the latest block of the network. -getChainTip :: MaestroEnv -> IO ChainTip +getChainTip :: MaestroEnv 'V0 -> IO ChainTip getChainTip = _chainTip . generalClient -- | Get network start time since genesis. -getSystemStart :: MaestroEnv -> IO SystemStart +getSystemStart :: MaestroEnv 'V0 -> IO SystemStart getSystemStart = _systemStart . generalClient -- | Get network era history. -getEraHistory :: MaestroEnv -> IO [EraSummary] +getEraHistory :: MaestroEnv 'V0 -> IO [EraSummary] getEraHistory = _eraHistory . generalClient -- | Get protocol parameters for the latest epoch. -getProtocolParameters :: MaestroEnv -> IO ProtocolParameters +getProtocolParameters :: MaestroEnv 'V0 -> IO ProtocolParameters getProtocolParameters = _protocolParams . generalClient diff --git a/src/Maestro/Client/V0/Pools.hs b/src/Maestro/Client/V0/Pools.hs index 841aafb..355a139 100644 --- a/src/Maestro/Client/V0/Pools.hs +++ b/src/Maestro/Client/V0/Pools.hs @@ -18,38 +18,38 @@ import Maestro.Types.V0 import Servant.API.Generic import Servant.Client -poolsClient :: MaestroEnv -> PoolAPI (AsClientT IO) +poolsClient :: MaestroEnv 'V0 -> PoolAPI (AsClientT IO) poolsClient = fromServant . _pools . apiV0Client -- | Returns a list of currently registered stake pools -listPools :: MaestroEnv -> Page -> IO [PoolListInfo] +listPools :: MaestroEnv 'V0 -> Page -> IO [PoolListInfo] listPools = _listPools . poolsClient -- | Return information about blocks minted by a given pool for all epochs -- (or just epoch `epoch_no` if provided) -poolBlocks :: MaestroEnv -> Bech32StringOf PoolId -> Page -> Maybe EpochNo -> Maybe Order -> IO [PoolBlock] +poolBlocks :: MaestroEnv 'V0 -> Bech32StringOf PoolId -> Page -> Maybe EpochNo -> Maybe Order -> IO [PoolBlock] poolBlocks = _poolBlocks . poolsClient -poolDelegators :: MaestroEnv -> Bech32StringOf PoolId -> Page -> IO [DelegatorInfo] +poolDelegators :: MaestroEnv 'V0 -> Bech32StringOf PoolId -> Page -> IO [DelegatorInfo] poolDelegators = _poolDelegators . poolsClient -- | Returns per-epoch information about the specified pool -- (or just epoch `epoch_no` if provided) -poolHistory :: MaestroEnv -> Bech32StringOf PoolId -> Page -> Maybe EpochNo -> Maybe Order -> IO [PoolHistory] +poolHistory :: MaestroEnv 'V0 -> Bech32StringOf PoolId -> Page -> Maybe EpochNo -> Maybe Order -> IO [PoolHistory] poolHistory = _poolHistory . poolsClient -- | Returns current information about the specified pool -poolInfo :: MaestroEnv -> Bech32StringOf PoolId -> IO PoolInfo +poolInfo :: MaestroEnv 'V0 -> Bech32StringOf PoolId -> IO PoolInfo poolInfo = _poolInfo . poolsClient -- | Returns the metadata declared by a specific pool -poolMetadata :: MaestroEnv -> Bech32StringOf PoolId -> IO PoolMetadata +poolMetadata :: MaestroEnv 'V0 -> Bech32StringOf PoolId -> IO PoolMetadata poolMetadata = _poolMetadata . poolsClient -- | Returns a list of relays declared by the specified pool -poolRelays :: MaestroEnv -> Bech32StringOf PoolId -> IO [PoolRelay] +poolRelays :: MaestroEnv 'V0 -> Bech32StringOf PoolId -> IO [PoolRelay] poolRelays = _poolRelays . poolsClient -- | Returns a list of updates relating to the specified pool -poolUpdates :: MaestroEnv -> Bech32StringOf PoolId -> IO [PoolUpdate] +poolUpdates :: MaestroEnv 'V0 -> Bech32StringOf PoolId -> IO [PoolUpdate] poolUpdates = _poolUpdates . poolsClient diff --git a/src/Maestro/Client/V0/Scripts.hs b/src/Maestro/Client/V0/Scripts.hs index c40641a..c7455a4 100644 --- a/src/Maestro/Client/V0/Scripts.hs +++ b/src/Maestro/Client/V0/Scripts.hs @@ -11,9 +11,9 @@ import Maestro.Types.V0 import Servant.API.Generic import Servant.Client -scriptsClient :: MaestroEnv -> ScriptsAPI (AsClientT IO) +scriptsClient :: MaestroEnv 'V0 -> ScriptsAPI (AsClientT IO) scriptsClient = fromServant . _scripts . apiV0Client -- | Get information about the script from it's hash. -getScriptByHash :: MaestroEnv -> Text -> IO Script +getScriptByHash :: MaestroEnv 'V0 -> Text -> IO Script getScriptByHash = _scriptByHash . scriptsClient diff --git a/src/Maestro/Client/V0/Transaction.hs b/src/Maestro/Client/V0/Transaction.hs index 641c561..02b5329 100644 --- a/src/Maestro/Client/V0/Transaction.hs +++ b/src/Maestro/Client/V0/Transaction.hs @@ -16,7 +16,7 @@ import Maestro.Types.V0 import Servant.API.Generic import Servant.Client -txClient :: MaestroEnv -> TxAPI (AsClientT IO) +txClient :: MaestroEnv 'V0 -> TxAPI (AsClientT IO) txClient = fromServant . _tx . apiV0Client -- | @@ -24,7 +24,7 @@ txClient = fromServant . _tx . apiV0Client -- Interaction with this endpoint is identical to IOG's Cardano Submit API and will not be monitored by Maestro. submitTx :: -- | The Maestro Environment - MaestroEnv -> + MaestroEnv 'V0 -> -- | CBOR encoded Transaction BS.ByteString -> IO Text @@ -34,7 +34,7 @@ submitTx = _submitTx . txClient -- Returns hex-encoded CBOR bytes of a transaction txCbor :: -- | The Maestro Environment - MaestroEnv -> + MaestroEnv 'V0 -> -- | Hex Encoded Transaction Hash HashStringOf Tx -> -- | hex-encoded CBOR bytes of a transaction @@ -45,7 +45,7 @@ txCbor = _txCborApi . txClient -- Returns the address specified in the given transaction output txAddress :: -- | The Maestro Environment - MaestroEnv -> + MaestroEnv 'V0 -> -- | Hex Encoded Transaction Hash HashStringOf Tx -> -- | The Transaction Output Index @@ -56,8 +56,8 @@ txAddress = _txAddressApi . txClient -- | -- Returns the specified transaction output of a transaction output reference txUtxo :: - -- | The MaestroEnv - MaestroEnv -> + -- | The Maestro Environment. + MaestroEnv 'V0 -> -- | Hex encoded transaction hash HashStringOf Tx -> -- | The Transaction Output Index diff --git a/src/Maestro/Client/V0/TxManager.hs b/src/Maestro/Client/V0/TxManager.hs index 6776ed6..171ab5b 100644 --- a/src/Maestro/Client/V0/TxManager.hs +++ b/src/Maestro/Client/V0/TxManager.hs @@ -12,7 +12,7 @@ import Maestro.Client.V0.Core import Servant.API.Generic import Servant.Client -txClient :: MaestroEnv -> TxManagerAPI (AsClientT IO) +txClient :: MaestroEnv 'V0 -> TxManagerAPI (AsClientT IO) txClient = fromServant . _txManager . apiV0Client -- | @@ -20,7 +20,7 @@ txClient = fromServant . _txManager . apiV0Client -- A transaction submited with this endpoint will be monitored by Maestro. submitAndMonitorTx :: -- | The Maestro Environment - MaestroEnv -> + MaestroEnv 'V0 -> -- | CBOR encoded Transaction BS.ByteString -> IO Text diff --git a/src/Maestro/Client/V1/Address.hs b/src/Maestro/Client/V1/Address.hs index cd9a0c8..c13f6b5 100644 --- a/src/Maestro/Client/V1/Address.hs +++ b/src/Maestro/Client/V1/Address.hs @@ -9,13 +9,13 @@ import Maestro.Types.V1 import Servant.API.Generic import Servant.Client -addressClient :: MaestroEnv -> AddressAPI (AsClientT IO) +addressClient :: MaestroEnv 'V1 -> AddressAPI (AsClientT IO) addressClient = fromServant . _address . apiV1Client -- | Returns list of utxos for multiple addresses utxosAtMultiAddresses :: -- | The Maestro Environment - MaestroEnv -> + MaestroEnv 'V1 -> -- | Query param to include the corresponding datums for datum hashes Maybe Bool -> -- | Query Param to include the CBOR encodings of the transaction outputs in the response diff --git a/src/Maestro/Client/V1/Core.hs b/src/Maestro/Client/V1/Core.hs index 638e983..266d1f6 100644 --- a/src/Maestro/Client/V1/Core.hs +++ b/src/Maestro/Client/V1/Core.hs @@ -12,8 +12,8 @@ import Servant.API.Generic (fromServant) import Servant.Client import Servant.Client.Generic -apiV1ClientAuth :: MaestroEnv -> MaestroApiV1Auth (AsClientT IO) +apiV1ClientAuth :: MaestroEnv 'V1 -> MaestroApiV1Auth (AsClientT IO) apiV1ClientAuth MaestroEnv{..} = genericClientHoist $ \x -> runClientM x _maeClientEnv >>= either (throwIO . fromServantClientError) pure -apiV1Client :: MaestroEnv -> MaestroApiV1 (AsClientT IO) +apiV1Client :: MaestroEnv 'V1 -> MaestroApiV1 (AsClientT IO) apiV1Client mEnv@MaestroEnv {..} = fromServant $ _apiV1 (apiV1ClientAuth mEnv) _maeToken From 4f6095ebe2431cc3e22d1c6a9719bbab7b704fa5 Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Thu, 6 Jul 2023 14:59:44 +0530 Subject: [PATCH 09/24] Feat 30: V1 Endpoints support - v1 to v0 UTxO conversion function to assert equality --- maestro-exe/Maestro/Run/Address.hs | 17 +++++++++++---- maestro-exe/Main.hs | 6 +++--- src/Maestro/Types/Common.hs | 12 +++++++---- src/Maestro/Types/V0/Common.hs | 7 +++--- src/Maestro/Types/V1/Common.hs | 34 +++++++++++++++++++++++++++--- 5 files changed, 59 insertions(+), 17 deletions(-) diff --git a/maestro-exe/Maestro/Run/Address.hs b/maestro-exe/Maestro/Run/Address.hs index 5fa3234..54d5fea 100644 --- a/maestro-exe/Maestro/Run/Address.hs +++ b/maestro-exe/Maestro/Run/Address.hs @@ -1,8 +1,17 @@ module Maestro.Run.Address where +import Control.Monad (when) +import Data.List (sort) import Maestro.Client.Env -import qualified Maestro.Client.V0 as V0 -import qualified Maestro.Client.V1 as V1 +import qualified Maestro.Client.V0 as V0 +import qualified Maestro.Client.V1 as V1 +import Maestro.Types.V1.Common (v1UtxoToV0) -runAddressAPI :: MaestroEnv 'V0 -> IO () -runAddressAPI mEnv = undefined +runAddressAPI :: MaestroEnv 'V0 -> MaestroEnv 'V1 -> IO () +runAddressAPI mEnvV0 mEnvV1 = do + let addrs = undefined -- Mention list of addresses. + utxos <- V0.allPages $ flip (V0.utxosAtMultiAddresses mEnvV0 Nothing Nothing) addrs + let utxosSorted = sort utxos + utxos' <- fmap (fmap v1UtxoToV0) $ V1.allPages $ flip (V1.utxosAtMultiAddresses mEnvV1 Nothing Nothing) addrs + let utxos'Sorted = sort utxos' + when (utxosSorted == utxos'Sorted) $ putStrLn "Yes" diff --git a/maestro-exe/Main.hs b/maestro-exe/Main.hs index 11b8f3c..f96d79a 100644 --- a/maestro-exe/Main.hs +++ b/maestro-exe/Main.hs @@ -24,9 +24,9 @@ main = do runDatumAPI env runScriptsAPI env runGeneralAPI env - -- env' <- mkMaestroEnv @'V1 (T.pack apiKeyMain) Mainnet - env' <- mkMaestroEnv @'V0 (T.pack apiKeyMain) Mainnet - runAddressAPI env' + envV1 <- mkMaestroEnv @'V1 (T.pack apiKeyMain) Mainnet + envV0 <- mkMaestroEnv @'V0 (T.pack apiKeyMain) Mainnet + runAddressAPI envV0 envV1 where maestroKey = getEnv "MAESTRO_API_KEY" diff --git a/src/Maestro/Types/Common.hs b/src/Maestro/Types/Common.hs index c8be6fa..eba5074 100644 --- a/src/Maestro/Types/Common.hs +++ b/src/Maestro/Types/Common.hs @@ -1,5 +1,6 @@ module Maestro.Types.Common ( Tx, + TxOutCbor, TxIndex (..), PolicyId (..), AssetId (..), @@ -41,6 +42,9 @@ import Servant.API -- | Phantom datatype to be used with constructors like `HashStringOf`. data Tx +-- | Phantom datatype to be used with `HexStringOf` to represent hex encoded CBOR bytes of transaction output. +data TxOutCbor + -- | Index of UTxO in a transaction outputs. newtype TxIndex = TxIndex Natural deriving stock (Eq, Ord, Show, Generic) @@ -106,7 +110,7 @@ newtype HashStringOf a = HashStringOf Text deriving newtype (FromHttpApiData, ToHttpApiData, FromJSON, ToJSON, IsString) data DatumOptionType = Inline | Hash - deriving stock (Show, Eq, Generic) + deriving stock (Show, Eq, Ord, Generic) deriving (FromJSON, ToJSON) via CustomJSON '[ConstructorTagModifier '[LowerFirst]] DatumOptionType data DatumOption = DatumOption @@ -115,13 +119,13 @@ data DatumOption = DatumOption _datumOptionJson :: !(Maybe Aeson.Value), _datumOptionType :: !DatumOptionType } - deriving stock (Show, Eq, Generic) + deriving stock (Show, Eq, Ord, Generic) deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_datumOption", LowerFirst]] DatumOption data ScriptType = Native | PlutusV1 | PlutusV2 - deriving stock (Show, Eq, Generic) + deriving stock (Show, Eq, Ord, Generic) deriving (FromJSON, ToJSON) via CustomJSON '[ConstructorTagModifier '[LowerAll]] ScriptType @@ -132,7 +136,7 @@ data Script = Script _scriptJson :: !(Maybe Aeson.Value), _scriptType :: !ScriptType } - deriving stock (Show, Eq, Generic) + deriving stock (Show, Eq, Ord, Generic) deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_script", LowerFirst]] Script diff --git a/src/Maestro/Types/V0/Common.hs b/src/Maestro/Types/V0/Common.hs index 646db5b..b8abb96 100644 --- a/src/Maestro/Types/V0/Common.hs +++ b/src/Maestro/Types/V0/Common.hs @@ -15,7 +15,7 @@ data Asset = Asset { _assetQuantity :: !Integer , _assetUnit :: !Text } - deriving stock (Show, Eq, Generic) + deriving stock (Show, Eq, Ord, Generic) deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_asset", CamelToSnake]] Asset @@ -27,9 +27,10 @@ data Utxo = Utxo _utxoDatum :: !(Maybe DatumOption), _utxoIndex :: !Natural, _utxoReferenceScript :: !(Maybe Script), - _utxoTxHash :: !Text + _utxoTxHash :: !Text, + _utxoTxoutCbor :: !(Maybe (HexStringOf TxOutCbor)) } - deriving stock (Show, Eq, Generic) + deriving stock (Show, Eq, Ord, Generic) deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_utxo", CamelToSnake]] Utxo diff --git a/src/Maestro/Types/V1/Common.hs b/src/Maestro/Types/V1/Common.hs index bcf117b..f4a5a65 100644 --- a/src/Maestro/Types/V1/Common.hs +++ b/src/Maestro/Types/V1/Common.hs @@ -1,17 +1,21 @@ module Maestro.Types.V1.Common ( LastUpdated (..), Asset (..), + v1AssetToV0, UtxoData (..), + v1UtxoToV0, Utxos (..), module Maestro.Types.Common ) where import Data.Text (Text) +import qualified Data.Text as T (splitAt) import Deriving.Aeson import GHC.Natural (Natural) import Maestro.Client.V1.Core.Pagination (HasCursor (..)) import Maestro.Types.Common +import qualified Maestro.Types.V0 as V0 (Asset (..), Utxo (..)) -- | Details of the most recent block processed by the indexer (aka chain tip); that is, the data returned is correct as of this block in time. data LastUpdated = LastUpdated @@ -28,11 +32,22 @@ data Asset = Asset { _assetAmount :: !Integer , _assetUnit :: !Text } - deriving stock (Show, Eq, Generic) + deriving stock (Show, Eq, Ord, Generic) deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_asset", CamelToSnake]] Asset +-- | Convert @V1@ API version `Asset` type into corresponding @V0@ type. +v1AssetToV0 :: Asset -> V0.Asset +v1AssetToV0 Asset {..} = V0.Asset { + V0._assetQuantity = _assetAmount + , V0._assetUnit = + if _assetUnit == "lovelace" then _assetUnit + else + let (policyId, tokenName) = T.splitAt 56 _assetUnit + in policyId <> "#" <> tokenName + } + -- | Transaction output. data UtxoData = UtxoData { _utxoDataAddress :: !Text, @@ -42,13 +57,26 @@ data UtxoData = UtxoData _utxoDataReferenceScript :: !(Maybe Script), _utxoDataTxHash :: !Text, _utxoDataSlot :: !SlotNo, - _utxoDataTxoutCbor :: !(Maybe TxCbor) + _utxoDataTxoutCbor :: !(Maybe (HexStringOf TxOutCbor)) + } - deriving stock (Show, Eq, Generic) + deriving stock (Show, Eq, Ord, Generic) deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_utxoData", CamelToSnake]] UtxoData +-- | Convert @V1@ API version `UtxoData` type into corresponding @V0@ type. +v1UtxoToV0 :: UtxoData -> V0.Utxo +v1UtxoToV0 UtxoData {..} = V0.Utxo { + V0._utxoAddress = _utxoDataAddress + , V0._utxoAssets = map v1AssetToV0 _utxoDataAssets + , V0._utxoDatum = _utxoDataDatum + , V0._utxoIndex = _utxoDataIndex + , V0._utxoReferenceScript = _utxoDataReferenceScript + , V0._utxoTxHash = _utxoDataTxHash + , V0._utxoTxoutCbor = _utxoDataTxoutCbor + } + -- | Transaction Outputs data Utxos = Utxos { _utxosData :: ![UtxoData], From 1efdc78bc5e2b3c9a1e9a44ae0e3ad983da156b5 Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Sun, 9 Jul 2023 21:22:08 +0530 Subject: [PATCH 10/24] Feat 30: V1 Endpoints support - support for endpoints needed for Atlas --- maestro-exe/Maestro/Run/Address.hs | 4 +- maestro-sdk.cabal | 19 ++- src/Maestro/API/V0/Address.hs | 10 +- src/Maestro/API/V1.hs | 16 ++- src/Maestro/API/V1/Address.hs | 20 --- src/Maestro/API/V1/Addresses.hs | 32 +++++ src/Maestro/API/V1/Datum.hs | 14 ++ src/Maestro/API/V1/Pools.hs | 14 ++ src/Maestro/API/V1/Transactions.hs | 19 +++ src/Maestro/API/V1/TxManager.hs | 15 ++ src/Maestro/Client/V1.hs | 4 +- src/Maestro/Client/V1/Address.hs | 28 ---- src/Maestro/Client/V1/Addresses.hs | 32 +++++ src/Maestro/Client/V1/Core/Pagination.hs | 26 ++-- src/Maestro/Client/V1/Datum.hs | 20 +++ src/Maestro/Client/V1/General.hs | 35 +++++ src/Maestro/Client/V1/Pools.hs | 21 +++ src/Maestro/Client/V1/Transactions.hs | 31 ++++ src/Maestro/Client/V1/TxManager.hs | 25 ++++ src/Maestro/Types/Common.hs | 85 ++++++----- src/Maestro/Types/V0.hs | 2 + src/Maestro/Types/V0/Common.hs | 11 +- src/Maestro/Types/V0/Transactions.hs | 22 +++ src/Maestro/Types/V1.hs | 12 +- src/Maestro/Types/V1/Addresses.hs | 101 +++++++++++++ src/Maestro/Types/V1/Common.hs | 168 +++++++++++++++------- src/Maestro/Types/V1/Common/Pagination.hs | 27 ++++ src/Maestro/Types/V1/Datum.hs | 20 +++ src/Maestro/Types/V1/General.hs | 10 +- src/Maestro/Types/V1/Pools.hs | 44 ++++++ src/Maestro/Types/V1/Transactions.hs | 80 +++++++++++ 31 files changed, 797 insertions(+), 170 deletions(-) delete mode 100644 src/Maestro/API/V1/Address.hs create mode 100644 src/Maestro/API/V1/Addresses.hs create mode 100644 src/Maestro/API/V1/Datum.hs create mode 100644 src/Maestro/API/V1/Pools.hs create mode 100644 src/Maestro/API/V1/Transactions.hs create mode 100644 src/Maestro/API/V1/TxManager.hs delete mode 100644 src/Maestro/Client/V1/Address.hs create mode 100644 src/Maestro/Client/V1/Addresses.hs create mode 100644 src/Maestro/Client/V1/Datum.hs create mode 100644 src/Maestro/Client/V1/General.hs create mode 100644 src/Maestro/Client/V1/Pools.hs create mode 100644 src/Maestro/Client/V1/Transactions.hs create mode 100644 src/Maestro/Client/V1/TxManager.hs create mode 100644 src/Maestro/Types/V0/Transactions.hs create mode 100644 src/Maestro/Types/V1/Addresses.hs create mode 100644 src/Maestro/Types/V1/Common/Pagination.hs create mode 100644 src/Maestro/Types/V1/Datum.hs create mode 100644 src/Maestro/Types/V1/Pools.hs create mode 100644 src/Maestro/Types/V1/Transactions.hs diff --git a/maestro-exe/Maestro/Run/Address.hs b/maestro-exe/Maestro/Run/Address.hs index 54d5fea..7322bc0 100644 --- a/maestro-exe/Maestro/Run/Address.hs +++ b/maestro-exe/Maestro/Run/Address.hs @@ -5,13 +5,13 @@ import Data.List (sort) import Maestro.Client.Env import qualified Maestro.Client.V0 as V0 import qualified Maestro.Client.V1 as V1 -import Maestro.Types.V1.Common (v1UtxoToV0) +import Maestro.Types.V1.Common (v1UtxoWithSlotToV0) runAddressAPI :: MaestroEnv 'V0 -> MaestroEnv 'V1 -> IO () runAddressAPI mEnvV0 mEnvV1 = do let addrs = undefined -- Mention list of addresses. utxos <- V0.allPages $ flip (V0.utxosAtMultiAddresses mEnvV0 Nothing Nothing) addrs let utxosSorted = sort utxos - utxos' <- fmap (fmap v1UtxoToV0) $ V1.allPages $ flip (V1.utxosAtMultiAddresses mEnvV1 Nothing Nothing) addrs + utxos' <- fmap (fmap v1UtxoWithSlotToV0) $ V1.allPages $ flip (V1.utxosAtMultiAddresses mEnvV1 Nothing Nothing) addrs let utxos'Sorted = sort utxos' when (utxosSorted == utxos'Sorted) $ putStrLn "Yes" diff --git a/maestro-sdk.cabal b/maestro-sdk.cabal index 23d4ba6..522432a 100644 --- a/maestro-sdk.cabal +++ b/maestro-sdk.cabal @@ -57,8 +57,12 @@ library Maestro.API.V0.TxManager Maestro.API.V1 - Maestro.API.V1.Address + Maestro.API.V1.Addresses + Maestro.API.V1.Datum Maestro.API.V1.General + Maestro.API.V1.Pools + Maestro.API.V1.Transactions + Maestro.API.V1.TxManager Maestro.Client.Env Maestro.Client.Error @@ -79,7 +83,12 @@ library Maestro.Client.V1 Maestro.Client.V1.Core Maestro.Client.V1.Core.Pagination - Maestro.Client.V1.Address + Maestro.Client.V1.Addresses + Maestro.Client.V1.Datum + Maestro.Client.V1.General + Maestro.Client.V1.Pools + Maestro.Client.V1.Transactions + Maestro.Client.V1.TxManager Maestro.Types.Common Maestro.Types.V0 @@ -91,10 +100,16 @@ library Maestro.Types.V0.Epochs Maestro.Types.V0.General Maestro.Types.V0.Pool + Maestro.Types.V0.Transactions Maestro.Types.V1 + Maestro.Types.V1.Addresses + Maestro.Types.V1.Datum Maestro.Types.V1.Common + Maestro.Types.V1.Common.Pagination Maestro.Types.V1.General + Maestro.Types.V1.Pools + Maestro.Types.V1.Transactions -- other-modules: -- other-extensions: diff --git a/src/Maestro/API/V0/Address.hs b/src/Maestro/API/V0/Address.hs index 2364288..f690007 100644 --- a/src/Maestro/API/V0/Address.hs +++ b/src/Maestro/API/V0/Address.hs @@ -1,6 +1,6 @@ module Maestro.API.V0.Address where -import Data.Text (Text) +import Data.Text (Text) import Maestro.Client.V0.Core.Pagination import Maestro.Types.V0 import Servant.API @@ -12,8 +12,8 @@ data AddressAPI route = AddressAPI _addressesUtxos :: route :- "utxos" - :> QueryParam "resolve_datums" Bool - :> QueryParam "with_cbor" Bool + :> QueryParam "resolve_datums" Bool + :> QueryParam "with_cbor" Bool :> Pagination :> ReqBody '[JSON] [Text] :> Post '[JSON] [Utxo] @@ -22,8 +22,8 @@ data AddressAPI route = AddressAPI :: route :- Capture "address" Text :> "utxos" - :> QueryParam "resolve_datums" Bool - :> QueryParam "with_cbor" Bool + :> QueryParam "resolve_datums" Bool + :> QueryParam "with_cbor" Bool :> Pagination :> Get '[JSON] [Utxo] diff --git a/src/Maestro/API/V1.hs b/src/Maestro/API/V1.hs index d30784f..d1f23d0 100644 --- a/src/Maestro/API/V1.hs +++ b/src/Maestro/API/V1.hs @@ -1,14 +1,22 @@ module Maestro.API.V1 where -import Data.Text (Text) -import Maestro.API.V1.Address +import Data.Text (Text) +import Maestro.API.V1.Addresses +import Maestro.API.V1.Datum import Maestro.API.V1.General +import Maestro.API.V1.Pools +import Maestro.API.V1.Transactions +import Maestro.API.V1.TxManager import Servant.API import Servant.API.Generic data MaestroApiV1 route = MaestroApiV1 - { _general :: route :- ToServantApi GeneralAPI - , _address :: route :- "addresses" :> ToServantApi AddressAPI + { _general :: route :- ToServantApi GeneralAPI + , _addresses :: route :- "addresses" :> ToServantApi AddressesAPI + , _datum :: route :- "datum" :> ToServantApi DatumAPI + , _pools :: route :- "pools" :> ToServantApi PoolsAPI + , _txManager :: route :- "txmanager" :> ToServantApi TxManagerAPI + , _transactions :: route :- ToServantApi TransactionsAPI } deriving Generic newtype MaestroApiV1Auth route = MaestroApiV1Auth diff --git a/src/Maestro/API/V1/Address.hs b/src/Maestro/API/V1/Address.hs deleted file mode 100644 index 0010530..0000000 --- a/src/Maestro/API/V1/Address.hs +++ /dev/null @@ -1,20 +0,0 @@ -module Maestro.API.V1.Address where - -import Data.Text (Text) -import Maestro.Client.V1.Core.Pagination -import Maestro.Types.V1 -import Servant.API -import Servant.API.Generic - -data AddressAPI route = AddressAPI - { - _addressesUtxos - :: route - :- "utxos" - :> QueryParam "resolve_datums" Bool - :> QueryParam "with_cbor" Bool - :> Pagination - :> ReqBody '[JSON] [Text] - :> Post '[JSON] Utxos - - } deriving (Generic) diff --git a/src/Maestro/API/V1/Addresses.hs b/src/Maestro/API/V1/Addresses.hs new file mode 100644 index 0000000..84071f4 --- /dev/null +++ b/src/Maestro/API/V1/Addresses.hs @@ -0,0 +1,32 @@ +module Maestro.API.V1.Addresses where + +import Maestro.Client.V1.Core.Pagination +import Maestro.Types.V1 +import Servant.API +import Servant.API.Generic + +data AddressesAPI route = AddressesAPI + { + _decodeAddress + :: route + :- Capture "address" (TaggedText AddressToDecode) + :> "decode" + :> Get '[JSON] AddressInfo + + , _addressesUtxos + :: route + :- "utxos" + :> QueryParam "resolve_datums" Bool + :> QueryParam "with_cbor" Bool + :> Pagination + :> ReqBody '[JSON] [Bech32StringOf Address] + :> Post '[JSON] PaginatedUtxoWithSlot + + -- , _addressUtxoRefs + -- :: route + -- :- Capture "address" Text + -- :> "utxo_refs" + -- :> Pagination + -- :> Get '[JSON] [UtxoRef] + + } deriving (Generic) diff --git a/src/Maestro/API/V1/Datum.hs b/src/Maestro/API/V1/Datum.hs new file mode 100644 index 0000000..62cb273 --- /dev/null +++ b/src/Maestro/API/V1/Datum.hs @@ -0,0 +1,14 @@ +module Maestro.API.V1.Datum where + +import Maestro.Types.V1 +import Servant.API +import Servant.API.Generic + +newtype DatumAPI route = + DatumAPI + { + _datumByHash + :: route + :- Capture "datum_hash" (HexStringOf DatumHash) + :> Get '[JSON] Datum + } deriving Generic diff --git a/src/Maestro/API/V1/Pools.hs b/src/Maestro/API/V1/Pools.hs new file mode 100644 index 0000000..21b1be4 --- /dev/null +++ b/src/Maestro/API/V1/Pools.hs @@ -0,0 +1,14 @@ +module Maestro.API.V1.Pools where + +import Maestro.Client.V1.Core.Pagination +import Maestro.Types.V1 +import Servant.API +import Servant.API.Generic + +data PoolsAPI route = PoolsAPI + { _listPools :: + route + :- Pagination + :> Get '[JSON] PaginatedPoolListInfo + } + deriving (Generic) diff --git a/src/Maestro/API/V1/Transactions.hs b/src/Maestro/API/V1/Transactions.hs new file mode 100644 index 0000000..72d382c --- /dev/null +++ b/src/Maestro/API/V1/Transactions.hs @@ -0,0 +1,19 @@ +module Maestro.API.V1.Transactions where + +import Maestro.Client.V1.Core.Pagination +import Maestro.Types.V1 +import Servant.API +import Servant.API.Generic + +newtype TransactionsAPI route = TransactionsAPI + { _txOutputs :: + route + :- "transactions" + :> "outputs" + :> QueryParam "resolve_datums" Bool + :> QueryParam "with_cbor" Bool + :> Pagination + :> ReqBody '[JSON] [OutputReference] + :> Post '[JSON] PaginatedUtxo + } + deriving (Generic) diff --git a/src/Maestro/API/V1/TxManager.hs b/src/Maestro/API/V1/TxManager.hs new file mode 100644 index 0000000..d388331 --- /dev/null +++ b/src/Maestro/API/V1/TxManager.hs @@ -0,0 +1,15 @@ +module Maestro.API.V1.TxManager where + +import qualified Data.ByteString as BS +import qualified Data.Text as T +import Maestro.Types.V1 +import Servant.API +import Servant.API.Generic + +newtype TxManagerAPI route = TxManagerAPI + { _monitoredTxSubmit :: + route + :- ReqBody' '[Required] '[CBORStream] BS.ByteString + :> PostAccepted '[JSON] T.Text + } + deriving (Generic) diff --git a/src/Maestro/Client/V1.hs b/src/Maestro/Client/V1.hs index 561d9ee..f86018f 100644 --- a/src/Maestro/Client/V1.hs +++ b/src/Maestro/Client/V1.hs @@ -2,11 +2,11 @@ module Maestro.Client.V1 ( module Maestro.Client.Env , module Maestro.Client.Error , module Maestro.Client.V1.Core - , module Maestro.Client.V1.Address + , module Maestro.Client.V1.Addresses ) where import Maestro.Client.Env import Maestro.Client.Error -import Maestro.Client.V1.Address +import Maestro.Client.V1.Addresses import Maestro.Client.V1.Core diff --git a/src/Maestro/Client/V1/Address.hs b/src/Maestro/Client/V1/Address.hs deleted file mode 100644 index c13f6b5..0000000 --- a/src/Maestro/Client/V1/Address.hs +++ /dev/null @@ -1,28 +0,0 @@ -module Maestro.Client.V1.Address where - -import Data.Text (Text) -import Maestro.API.V1 -import Maestro.API.V1.Address -import Maestro.Client.Env -import Maestro.Client.V1.Core -import Maestro.Types.V1 -import Servant.API.Generic -import Servant.Client - -addressClient :: MaestroEnv 'V1 -> AddressAPI (AsClientT IO) -addressClient = fromServant . _address . apiV1Client - --- | Returns list of utxos for multiple addresses -utxosAtMultiAddresses :: - -- | The Maestro Environment - MaestroEnv 'V1 -> - -- | Query param to include the corresponding datums for datum hashes - Maybe Bool -> - -- | Query Param to include the CBOR encodings of the transaction outputs in the response - Maybe Bool -> - -- | The pagination attributes - Cursor -> - -- | List of Address in bech32 format to fetch utxo from - [Text] -> - IO Utxos -utxosAtMultiAddresses = _addressesUtxos . addressClient diff --git a/src/Maestro/Client/V1/Addresses.hs b/src/Maestro/Client/V1/Addresses.hs new file mode 100644 index 0000000..f6fa1c9 --- /dev/null +++ b/src/Maestro/Client/V1/Addresses.hs @@ -0,0 +1,32 @@ +-- | Module to query for /"addresses"/ category of endpoints defined at [docs.gomaestro.org](https://docs.gomaestro.org/docs/category/addresses). + +module Maestro.Client.V1.Addresses ( + utxosAtMultiAddresses, + ) where + +import Maestro.API.V1 +import Maestro.API.V1.Addresses +import Maestro.Client.Env +import Maestro.Client.V1.Core +import Maestro.Types.Common (Address, Bech32StringOf) +import Maestro.Types.V1 (PaginatedUtxoWithSlot) +import Servant.API.Generic +import Servant.Client + +addressClient :: MaestroEnv 'V1 -> AddressesAPI (AsClientT IO) +addressClient = fromServant . _addresses . apiV1Client + +-- | Returns list of utxos for multiple addresses. +utxosAtMultiAddresses :: + -- | The Maestro Environment. + MaestroEnv 'V1 -> + -- | Query param to include the corresponding datums for datum hashes. + Maybe Bool -> + -- | Query Param to include the CBOR encodings of the transaction outputs in the response. + Maybe Bool -> + -- | The pagination attributes. + Cursor -> + -- | List of Address in bech32 format to fetch utxo from. + [Bech32StringOf Address] -> + IO PaginatedUtxoWithSlot +utxosAtMultiAddresses = _addressesUtxos . addressClient diff --git a/src/Maestro/Client/V1/Core/Pagination.hs b/src/Maestro/Client/V1/Core/Pagination.hs index 1e292c9..1558cb5 100644 --- a/src/Maestro/Client/V1/Core/Pagination.hs +++ b/src/Maestro/Client/V1/Core/Pagination.hs @@ -1,18 +1,18 @@ module Maestro.Client.V1.Core.Pagination where import Data.Default.Class -import Data.Kind (Type) -import Data.Maybe (isNothing) -import Data.Proxy (Proxy (..)) -import Data.Text (Text) -import Servant.API (QueryParam, (:>)) -import Servant.Client.Core (Client, HasClient, clientWithRoute, - hoistClientMonad) +import Data.Maybe (isNothing) +import Data.Proxy (Proxy (..)) +import Maestro.Types.V1.Common.Pagination +import Servant.API (QueryParam, (:>)) +import Servant.Client.Core (Client, HasClient, + clientWithRoute, + hoistClientMonad) -- | Pagination parameters. data Cursor = Cursor - { resultPerPage :: !Int -- ^ Total result to have per page. - , cursor :: !(Maybe Text) -- ^ Cursor. + { resultPerPage :: !Int -- ^ Total result to have per page. + , cursor :: !(Maybe NextCursor) -- ^ Cursor. } -- | Maximum number of result per page. @@ -22,12 +22,6 @@ maxResultsPerPage = 100 instance Default Cursor where def = Cursor maxResultsPerPage Nothing --- | Is the endpoint paged? -class (Monoid (CursorData a)) => HasCursor a where - type CursorData a :: Type - getNextCursor :: a -> Maybe Text - getCursorData :: a -> CursorData a - -- Utility for querying all results from a paged endpoint. allPages :: (Monad m, HasCursor a) => (Cursor -> m a) -> m (CursorData a) allPages act = fetch Nothing @@ -46,7 +40,7 @@ data Pagination type PaginationApi api = QueryParam "count" Int - :> QueryParam "cursor" Text + :> QueryParam "cursor" NextCursor :> api instance HasClient m api => HasClient m (Pagination :> api) where diff --git a/src/Maestro/Client/V1/Datum.hs b/src/Maestro/Client/V1/Datum.hs new file mode 100644 index 0000000..8c369be --- /dev/null +++ b/src/Maestro/Client/V1/Datum.hs @@ -0,0 +1,20 @@ +-- | Module to query for /"datum"/ category of endpoints defined at [docs.gomaestro.org](https://docs.gomaestro.org/docs/category/datum). + +module Maestro.Client.V1.Datum + ( getDatumByHash + ) where + +import Maestro.API.V1 (_datum) +import Maestro.API.V1.Datum +import Maestro.Client.Env +import Maestro.Client.V1.Core +import Maestro.Types.V1 +import Servant.API.Generic +import Servant.Client + +datumClient :: MaestroEnv 'V1 -> DatumAPI (AsClientT IO) +datumClient = fromServant . _datum . apiV1Client + +-- | Get information about the datum from it's hash. +getDatumByHash :: MaestroEnv 'V1 -> HexStringOf DatumHash -> IO Datum +getDatumByHash = _datumByHash . datumClient diff --git a/src/Maestro/Client/V1/General.hs b/src/Maestro/Client/V1/General.hs new file mode 100644 index 0000000..59a7579 --- /dev/null +++ b/src/Maestro/Client/V1/General.hs @@ -0,0 +1,35 @@ +-- | Module to query for /"general"/ category of endpoints defined at [docs.gomaestro.org](https://docs.gomaestro.org/docs/category/general). + +module Maestro.Client.V1.General + ( getChainTip + , getSystemStart + , getEraHistory + , getProtocolParameters + ) where + +import Maestro.API.V1 (_general) +import Maestro.API.V1.General +import Maestro.Client.Env +import Maestro.Client.V1.Core +import Maestro.Types.V1 +import Servant.API.Generic +import Servant.Client + +generalClient :: MaestroEnv 'V1 -> GeneralAPI (AsClientT IO) +generalClient = fromServant . _general . apiV1Client + +-- | Get details about the latest block of the network. +getChainTip :: MaestroEnv 'V1 -> IO ChainTip +getChainTip = _chainTip . generalClient + +-- | Get network start time since genesis. +getSystemStart :: MaestroEnv 'V1 -> IO SystemStart +getSystemStart = _systemStart . generalClient + +-- | Get network era history. +getEraHistory :: MaestroEnv 'V1 -> IO EraSummaries +getEraHistory = _eraHistory . generalClient + +-- | Get protocol parameters for the latest epoch. +getProtocolParameters :: MaestroEnv 'V1 -> IO ProtocolParameters +getProtocolParameters = _protocolParams . generalClient diff --git a/src/Maestro/Client/V1/Pools.hs b/src/Maestro/Client/V1/Pools.hs new file mode 100644 index 0000000..cad7af3 --- /dev/null +++ b/src/Maestro/Client/V1/Pools.hs @@ -0,0 +1,21 @@ +-- | Module to query for /"pools"/ category of endpoints defined at [docs.gomaestro.org](https://docs.gomaestro.org/docs/category/pools). + +module Maestro.Client.V1.Pools + ( listPools, + ) +where + +import Maestro.API.V1 +import Maestro.API.V1.Pools +import Maestro.Client.Env +import Maestro.Client.V1.Core +import Maestro.Types.V1 +import Servant.API.Generic +import Servant.Client + +poolsClient :: MaestroEnv 'V1 -> PoolsAPI (AsClientT IO) +poolsClient = fromServant . _pools . apiV1Client + +-- | Returns a list of currently registered stake pools +listPools :: MaestroEnv 'V1 -> Cursor -> IO PaginatedPoolListInfo +listPools = _listPools . poolsClient diff --git a/src/Maestro/Client/V1/Transactions.hs b/src/Maestro/Client/V1/Transactions.hs new file mode 100644 index 0000000..96f4e75 --- /dev/null +++ b/src/Maestro/Client/V1/Transactions.hs @@ -0,0 +1,31 @@ +-- | Module to query for /"transactions"/ category of endpoints defined at [docs.gomaestro.org](https://docs.gomaestro.org/docs/category/transactions). + +module Maestro.Client.V1.Transactions + ( outputsByReferences, + ) where + +import Maestro.API.V1 (_transactions) +import Maestro.API.V1.Transactions +import Maestro.Client.Env +import Maestro.Client.V1.Core +import Maestro.Types.V1 +import Servant.API.Generic +import Servant.Client + +txClient :: MaestroEnv 'V1 -> TransactionsAPI (AsClientT IO) +txClient = fromServant . _transactions . apiV1Client + +-- | Returns outputs for given output references. +outputsByReferences :: + -- | The Maestro Environment. + MaestroEnv 'V1 -> + -- | Try find and include the corresponding datums for datum hashes. + Maybe Bool -> + -- | Include the CBOR encodings of the transaction outputs in the response. + Maybe Bool -> + -- | The pagination attributes. + Cursor -> + -- | Output references. + [OutputReference] -> + IO PaginatedUtxo +outputsByReferences = _txOutputs . txClient diff --git a/src/Maestro/Client/V1/TxManager.hs b/src/Maestro/Client/V1/TxManager.hs new file mode 100644 index 0000000..49c69a6 --- /dev/null +++ b/src/Maestro/Client/V1/TxManager.hs @@ -0,0 +1,25 @@ +module Maestro.Client.V1.TxManager + ( submitAndMonitorTx + ) +where + +import qualified Data.ByteString as BS +import Data.Text (Text) +import Maestro.API.V1 (_txManager) +import Maestro.API.V1.TxManager +import Maestro.Client.Env +import Maestro.Client.V1.Core +import Servant.API.Generic +import Servant.Client + +txClient :: MaestroEnv 'V1 -> TxManagerAPI (AsClientT IO) +txClient = fromServant . _txManager . apiV1Client + +-- | Submit a signed and serialized transaction to the network. A transaction submited with this endpoint will be monitored by Maestro. +submitAndMonitorTx :: + -- | The Maestro Environment + MaestroEnv 'V1 -> + -- | CBOR encoded Transaction + BS.ByteString -> + IO Text +submitAndMonitorTx = _monitoredTxSubmit . txClient diff --git a/src/Maestro/Types/Common.hs b/src/Maestro/Types/Common.hs index eba5074..163c017 100644 --- a/src/Maestro/Types/Common.hs +++ b/src/Maestro/Types/Common.hs @@ -1,10 +1,13 @@ +-- | Common (shared) types between different versions of Maestro-API. + module Maestro.Types.Common ( Tx, TxOutCbor, + DatumHash, + Address, TxIndex (..), PolicyId (..), - AssetId (..), - CBORStream, + TokenName (..), EpochNo (..), EpochSize (..), AbsoluteSlot (..), @@ -13,16 +16,16 @@ module Maestro.Types.Common BlockHash (..), TxHash (..), Bech32StringOf (..), - HexStringOf, + HexStringOf (..), HashStringOf (..), DatumOptionType (..), DatumOption (..), ScriptType (..), Script (..), - TxCbor (..), - UtxoAddress (..), Order (..), + CBORStream, LowerFirst, + LowerAll, ) where @@ -45,20 +48,26 @@ data Tx -- | Phantom datatype to be used with `HexStringOf` to represent hex encoded CBOR bytes of transaction output. data TxOutCbor +-- | Phantom datatype to be used with `HexStringOf` to represent hex encoded datum hash. +data DatumHash + +-- | Phantom datatype to be used with, say `Bech32StringOf` to represent Bech32 representation of an address. +data Address + -- | Index of UTxO in a transaction outputs. newtype TxIndex = TxIndex Natural deriving stock (Eq, Ord, Show, Generic) deriving newtype (Num, Enum, Real, Integral, FromHttpApiData, ToHttpApiData, FromJSON, ToJSON) --- | Minting policy ID. +-- | Hex encoded minting policy ID (for non-ada native asset). newtype PolicyId = PolicyId Text - deriving stock (Eq, Show, Generic) + deriving stock (Eq, Ord, Show, Generic) deriving newtype (FromHttpApiData, ToHttpApiData, FromJSON, ToJSON, IsString) --- | Concatenation of hex encoded policy ID and hex encoded asset name. -newtype AssetId = AssetId Text +-- | Hex encoded token name (for non-ada native asset). +newtype TokenName = TokenName Text deriving stock (Eq, Ord, Show, Generic) - deriving newtype (FromHttpApiData, ToHttpApiData, FromJSON, ToJSON) + deriving newtype (FromHttpApiData, ToHttpApiData, FromJSON, ToJSON, IsString) -- | An epoch, i.e. the number of the epoch. newtype EpochNo = EpochNo {unEpochNo :: Word64} @@ -94,78 +103,84 @@ newtype BlockHash = BlockHash {unBlockHash :: Text} deriving (FromJSON, ToJSON) -- | Hash of the Transaction. -newtype TxHash = TxHash {unTxHash :: Text} - deriving stock (Show, Eq, Generic) - deriving newtype (IsString) - deriving (FromJSON, ToJSON) +newtype TxHash = TxHash Text + deriving stock (Show, Eq, Ord, Generic) + deriving newtype (FromHttpApiData, ToHttpApiData, FromJSON, ToJSON, IsString) +-- | Type to label the string is question is a @Bech32@ representation of the given type @a@. newtype Bech32StringOf a = Bech32StringOf Text - deriving stock (Eq, Show, Generic) + deriving stock (Eq, Ord, Show, Generic) deriving newtype (FromHttpApiData, ToHttpApiData, FromJSON, ToJSON, IsString) -type HexStringOf a = Text +-- | Type to label the string is question is a hexadecimal representation of the given type @a@. +newtype HexStringOf a = HexStringOf Text + deriving stock (Eq, Ord, Show, Generic) + deriving newtype (FromHttpApiData, ToHttpApiData, FromJSON, ToJSON, IsString) +-- | Type to label the string is question is a hash string of the given type @a@, like hash of the transaction body. newtype HashStringOf a = HashStringOf Text - deriving stock (Eq, Show, Generic) + deriving stock (Eq, Ord, Show, Generic) deriving newtype (FromHttpApiData, ToHttpApiData, FromJSON, ToJSON, IsString) +-- | Datum in output is either inlined or not. data DatumOptionType = Inline | Hash deriving stock (Show, Eq, Ord, Generic) deriving (FromJSON, ToJSON) via CustomJSON '[ConstructorTagModifier '[LowerFirst]] DatumOptionType +-- | Description of datum in an output. If datum is successfully resolved for (when mentioning to resolve for it by giving @resolve_datums@ flag in query parameters) then fields like @_datumOptionBytes@ would have non `Nothing` value even if UTxO just had hash of datum. data DatumOption = DatumOption { _datumOptionBytes :: !(Maybe Text), + -- ^ Hex encoded datum CBOR bytes. _datumOptionHash :: !Text, + -- ^ Hash of the datum. _datumOptionJson :: !(Maybe Aeson.Value), + -- ^ JSON representation of the datum. _datumOptionType :: !DatumOptionType + -- ^ See `DatumOptionType`. } deriving stock (Show, Eq, Ord, Generic) deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_datumOption", LowerFirst]] DatumOption +-- | Type of script. data ScriptType = Native | PlutusV1 | PlutusV2 deriving stock (Show, Eq, Ord, Generic) deriving (FromJSON, ToJSON) via CustomJSON '[ConstructorTagModifier '[LowerAll]] ScriptType +-- | Type to represent script in an UTxO. data Script = Script { _scriptBytes :: !(Maybe Text), + -- ^ Script bytes (`Nothing` if `Native` script). _scriptHash :: !Text, + -- ^ Hash of script. _scriptJson :: !(Maybe Aeson.Value), + -- ^ JSON representation of script (`Nothing` if not `Native` script). _scriptType :: !ScriptType + -- ^ See `ScriptType`. } deriving stock (Show, Eq, Ord, Generic) deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_script", LowerFirst]] Script -newtype TxCbor = TxCbor {_txCbor :: Text} - deriving stock (Show, Eq, Generic) - deriving - (FromJSON, ToJSON) - via CustomJSON '[FieldLabelModifier '[StripPrefix "_tx", LowerFirst]] TxCbor - -newtype UtxoAddress = UtxoAddress {_utxoAddressAddress :: Text} - deriving stock (Show, Eq, Generic) - deriving - (FromJSON, ToJSON) - via CustomJSON '[FieldLabelModifier '[StripPrefix "_utxoAddress", LowerFirst]] UtxoAddress - +-- Datatype to represent for /"order"/ query parameter in some of the API requests. data Order = Ascending | Descending +-- Don't change @Show@ instance blindly, as `ToHttpApiData` instance is making use of it. +instance Show Order where + show Ascending = "asc" + show Descending = "desc" + instance ToHttpApiData Order where - toQueryParam Ascending = "asc" - toQueryParam Descending = "desc" + toQueryParam order = T.pack $ show order instance Default Order where def = Ascending -instance Show Order where - show Ascending = "asc" - show Descending = "desc" - +-- | Content-Type to represent transaction when submitting for it. data CBORStream instance Accept CBORStream where diff --git a/src/Maestro/Types/V0.hs b/src/Maestro/Types/V0.hs index 7c8a65a..26a45a5 100644 --- a/src/Maestro/Types/V0.hs +++ b/src/Maestro/Types/V0.hs @@ -9,6 +9,7 @@ module Maestro.Types.V0 , module Maestro.Types.V0.Common , module Maestro.Types.V0.General , module Maestro.Types.V0.Pool + , module Maestro.Types.V0.Transactions ) where import Maestro.Types.V0.Accounts @@ -19,3 +20,4 @@ import Maestro.Types.V0.Datum import Maestro.Types.V0.Epochs import Maestro.Types.V0.General import Maestro.Types.V0.Pool +import Maestro.Types.V0.Transactions diff --git a/src/Maestro/Types/V0/Common.hs b/src/Maestro/Types/V0/Common.hs index b8abb96..950b965 100644 --- a/src/Maestro/Types/V0/Common.hs +++ b/src/Maestro/Types/V0/Common.hs @@ -1,5 +1,6 @@ module Maestro.Types.V0.Common - ( Asset (..), + ( AssetId (..), + Asset (..), Utxo (..), module Maestro.Types.Common ) @@ -9,6 +10,12 @@ import Data.Text (Text) import Deriving.Aeson import GHC.Natural (Natural) import Maestro.Types.Common +import Servant.API (FromHttpApiData, ToHttpApiData) + +-- | Concatenation of hex encoded policy ID and hex encoded asset name. +newtype AssetId = AssetId Text + deriving stock (Eq, Ord, Show, Generic) + deriving newtype (FromHttpApiData, ToHttpApiData, FromJSON, ToJSON) -- | Representation of asset in an UTxO. data Asset = Asset @@ -22,7 +29,7 @@ data Asset = Asset -- | Transaction output. data Utxo = Utxo - { _utxoAddress :: !Text, + { _utxoAddress :: !(Bech32StringOf Address), _utxoAssets :: ![Asset], _utxoDatum :: !(Maybe DatumOption), _utxoIndex :: !Natural, diff --git a/src/Maestro/Types/V0/Transactions.hs b/src/Maestro/Types/V0/Transactions.hs new file mode 100644 index 0000000..dd98e18 --- /dev/null +++ b/src/Maestro/Types/V0/Transactions.hs @@ -0,0 +1,22 @@ +module Maestro.Types.V0.Transactions + ( TxCbor (..), + UtxoAddress (..), + ) +where + +import Data.Text (Text) +import Deriving.Aeson +import Maestro.Types.Common (LowerFirst) + +newtype TxCbor = TxCbor { _txCbor :: Text } + deriving stock (Show, Eq, Generic) + deriving + (FromJSON, ToJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "_tx", LowerFirst]] TxCbor + +newtype UtxoAddress = UtxoAddress { _utxoAddressAddress :: Text } + deriving stock (Show, Eq, Generic) + deriving + (FromJSON, ToJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "_utxoAddress", LowerFirst]] UtxoAddress + diff --git a/src/Maestro/Types/V1.hs b/src/Maestro/Types/V1.hs index ae3cb26..3bc07f6 100644 --- a/src/Maestro/Types/V1.hs +++ b/src/Maestro/Types/V1.hs @@ -1,9 +1,17 @@ --- | Maestro types +-- | Module exporting all available types of this specific Maestro-API version. module Maestro.Types.V1 - ( module Maestro.Types.V1.Common + ( module Maestro.Types.V1.Addresses + , module Maestro.Types.V1.Common + , module Maestro.Types.V1.Datum , module Maestro.Types.V1.General + , module Maestro.Types.V1.Pools + , module Maestro.Types.V1.Transactions ) where +import Maestro.Types.V1.Addresses import Maestro.Types.V1.Common +import Maestro.Types.V1.Datum import Maestro.Types.V1.General +import Maestro.Types.V1.Pools +import Maestro.Types.V1.Transactions diff --git a/src/Maestro/Types/V1/Addresses.hs b/src/Maestro/Types/V1/Addresses.hs new file mode 100644 index 0000000..76c208c --- /dev/null +++ b/src/Maestro/Types/V1/Addresses.hs @@ -0,0 +1,101 @@ +-- | Module to define types for /\"Addresses\"/ category of endpoints defined at [docs.gomaestro.org](https://docs.gomaestro.org/docs/category/addresses). + +module Maestro.Types.V1.Addresses ( + AddressToDecode, + NetworkId (..), + PaymentCredKind (..), + PaymentCredential (..), + StakingCredKind (..), + CertIndex (..), + ChainPointer (..), + StakingCredential (..), + AddressInfo (..), + ) where + +import Deriving.Aeson +import GHC.Natural (Natural) +import Maestro.Types.V1.Common +import Servant.API (FromHttpApiData, ToHttpApiData) + +-- | Address to decode. Given address should be in either Bech32 or Hex or Base58 format. Base58 is for Byron addresses whereas others use Bech32. +type AddressToDecode = "Bech32/Hex/Base58 encoded address" + +-- | Denotes network for the entity in question, such as address. +data NetworkId = Mainnet | Testnet + deriving stock (Show, Eq, Ord, Generic) + deriving (FromJSON, ToJSON) via CustomJSON '[ConstructorTagModifier '[LowerFirst]] NetworkId + +-- | Denotes kind of a payment credential. +data PaymentCredKind = PCKKey | PCKScript + deriving stock (Show, Eq, Ord, Generic) + deriving (FromJSON, ToJSON) via CustomJSON '[ConstructorTagModifier '[StripPrefix "PCK", LowerFirst]] PaymentCredKind + +-- | Payment credential, the payment part of a Cardano address. +data PaymentCredential = PaymentCredential + { _paymentCredentialBech32:: !(Bech32StringOf PaymentCredentialAddress) + -- ^ Bech32-encoding of the credential key hash or script hash. + , _paymentCredentialHex :: !(HexStringOf PaymentCredentialAddress) + -- ^ Hex-encoding of the script or key credential. + , _paymentCredentialKind :: !PaymentCredKind + -- ^ See `PaymentCredKind`. + } + deriving stock (Show, Eq, Ord, Generic) + deriving (FromJSON, ToJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "_paymentCredential", CamelToSnake]] PaymentCredential + +-- | Denotes kind of a staking credential. +data StakingCredKind = SCKKey | SCKScript | SCKPointer + deriving stock (Show, Eq, Ord, Generic) + deriving (FromJSON, ToJSON) via CustomJSON '[ConstructorTagModifier '[StripPrefix "SCK", LowerFirst]] StakingCredKind + +-- | To understand it, see it's use in `ChainPointer` datatype. +newtype CertIndex = CertIndex Natural + deriving stock (Eq, Ord, Show, Generic) + deriving newtype (Num, Enum, Real, Integral, FromHttpApiData, ToHttpApiData, FromJSON, ToJSON) + +-- | In an address, a chain pointer refers to a point of the chain containing a stake key registration certificate. A point is identified by 3 coordinates, as listed in the type. +data ChainPointer = ChainPointer + { _chainPointerSlot :: !SlotNo + -- ^ An absolute slot number. + , _chainPointerTxIndex :: !TxIndex + -- ^ A transaction index (within that slot). + , _chainPointerCertIndex :: !CertIndex + -- ^ A (delegation) certificate index (within that transaction). + } + deriving stock (Show, Eq, Ord, Generic) + deriving (FromJSON, ToJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "_chainPointer", CamelToSnake]] ChainPointer + +-- | Payment credential, the payment part of a Cardano address. +data StakingCredential = StakingCredential + { _stakingCredentialBech32:: !(Maybe (Bech32StringOf StakingCredentialAddress)) + -- ^ Bech32-encoding of the credential key hash or script hash. + , _stakingCredentialHex :: !(Maybe (HexStringOf StakingCredentialAddress)) + -- ^ Hex-encoding of the script or key credential. + , _stakingCredentialKind :: !StakingCredKind + -- ^ See `StakingCredKind`. + , _stakingCredentialPointer :: !(Maybe ChainPointer) + -- ^ See `ChainPointer`. + , _stakingCredentialRewardAddress :: !(Maybe (Bech32StringOf RewardAddress)) + -- ^ See `RewardAddress`. + } + deriving stock (Show, Eq, Ord, Generic) + deriving (FromJSON, ToJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "_stakingCredential", CamelToSnake]] StakingCredential + +-- | Information decoded from a Cardano address. +data AddressInfo = AddressInfo + { _addressInfoHex :: !(HexStringOf Address) + -- ^ Hexadecimal format encoding of the given address. + , _addressInfoBech32 :: !(Maybe (Bech32StringOf Address)) + -- ^ Bech32 representation of the given address. Present for Shelly & stake addresses whereas byron addresses are encoded in Base58. + , _addressInfoNetwork :: !(Maybe NetworkId) + -- ^ See `NetworkId`. + , _addressInfoPaymentCred :: !(Maybe PaymentCredential) + -- ^ See `PaymentCredential`. + , _addressInfoStakingCred :: !(Maybe StakingCredential) + -- ^ See `StakingCredential`. + } + deriving stock (Show, Eq, Ord, Generic) + deriving (FromJSON, ToJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "_addressInfo", CamelToSnake]] AddressInfo diff --git a/src/Maestro/Types/V1/Common.hs b/src/Maestro/Types/V1/Common.hs index f4a5a65..c87af4a 100644 --- a/src/Maestro/Types/V1/Common.hs +++ b/src/Maestro/Types/V1/Common.hs @@ -1,21 +1,48 @@ +-- | Common (shared) types used which are not specific to single category of endpoints. + module Maestro.Types.V1.Common - ( LastUpdated (..), + ( PaymentCredentialAddress, + StakingCredentialAddress, + RewardAddress, + TaggedText (..), + LastUpdated (..), Asset (..), v1AssetToV0, - UtxoData (..), - v1UtxoToV0, - Utxos (..), - module Maestro.Types.Common - ) -where - -import Data.Text (Text) -import qualified Data.Text as T (splitAt) + UtxoWithSlot (..), + v1UtxoWithSlotToV0, + PaginatedUtxoWithSlot (..), + module Maestro.Types.Common, + module Maestro.Types.V1.Common.Pagination + ) where + +import Data.Aeson (FromJSON (..), ToJSON (..), + Value (..), withText) +import Data.Coerce (coerce) +import Data.String (IsString) +import Data.Text (Text) +import qualified Data.Text as T (splitAt) import Deriving.Aeson -import GHC.Natural (Natural) -import Maestro.Client.V1.Core.Pagination (HasCursor (..)) +import GHC.TypeLits (Symbol) import Maestro.Types.Common -import qualified Maestro.Types.V0 as V0 (Asset (..), Utxo (..)) +import qualified Maestro.Types.V0 as V0 (Asset (..), + Utxo (..)) +import Maestro.Types.V1.Common.Pagination +import Servant.API (FromHttpApiData (..), + ToHttpApiData (..)) + +-- | Phantom datatype to be used with, say `Bech32StringOf` to represent Bech32 representation of payment credential of an address. +data PaymentCredentialAddress + +-- | Phantom datatype to be used with, say `Bech32StringOf` to represent Bech32 representation of staking credential of an address. +data StakingCredentialAddress + +-- | Phantom datatype to be used with, say `Bech32StringOf` to represent Bech32 representation of stake address (See [CIP-19](https://cips.cardano.org/cips/cip19/) for more details). +data RewardAddress + +-- | Wrapper around `Text` type with mentioned description of it. +newtype TaggedText (description :: Symbol) = TaggedText Text + deriving stock (Eq, Ord, Show, Generic) + deriving newtype (FromHttpApiData, ToHttpApiData, FromJSON, ToJSON, IsString) -- | Details of the most recent block processed by the indexer (aka chain tip); that is, the data returned is correct as of this block in time. data LastUpdated = LastUpdated @@ -27,10 +54,41 @@ data LastUpdated = LastUpdated deriving stock (Eq, Ord, Show, Generic) deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_lastUpdated", CamelToSnake]] LastUpdated +-- | Type to denote for native tokens (besides ada). +data NonAdaNativeToken = NonAdaNativeToken !PolicyId !TokenName + deriving stock (Eq, Ord, Show) + +instance ToHttpApiData NonAdaNativeToken where + toUrlPiece (NonAdaNativeToken policyId tokenName) = coerce policyId <> coerce tokenName + +-- | Given asset name is either /lovelace/ or concatenation of hex encoded policy ID and hex encoded asset name for native asset. +data AssetUnit = Lovelace + -- ^ Lovelace. + | UserMintedToken !NonAdaNativeToken + -- ^ For non-ada native-tokens. + deriving stock (Eq, Ord) + +instance Show AssetUnit where + show Lovelace = "lovelace" + show (UserMintedToken nonAdaNativeToken) = show nonAdaNativeToken + +instance FromJSON AssetUnit where + parseJSON = withText "AssetUnit" $ \t -> + if t == "lovelace" then pure Lovelace + else + let (policyId, tokenName) = T.splitAt 56 t + in pure $ UserMintedToken $ NonAdaNativeToken (coerce policyId) (coerce tokenName) + +instance ToJSON AssetUnit where + toJSON Lovelace = String "lovelace" + toJSON (UserMintedToken nonAdaNativeToken) = String $ toUrlPiece nonAdaNativeToken + -- | Representation of asset in an UTxO. data Asset = Asset { _assetAmount :: !Integer - , _assetUnit :: !Text + -- ^ Amount of the asset. + , _assetUnit :: !AssetUnit + -- ^ See `AssetUnit`. } deriving stock (Show, Eq, Ord, Generic) deriving @@ -41,54 +99,62 @@ data Asset = Asset v1AssetToV0 :: Asset -> V0.Asset v1AssetToV0 Asset {..} = V0.Asset { V0._assetQuantity = _assetAmount - , V0._assetUnit = - if _assetUnit == "lovelace" then _assetUnit - else - let (policyId, tokenName) = T.splitAt 56 _assetUnit - in policyId <> "#" <> tokenName + , V0._assetUnit = case _assetUnit of + Lovelace -> "lovelace" + UserMintedToken (NonAdaNativeToken policyId tokenName) -> coerce policyId <> "#" <> coerce tokenName } -- | Transaction output. -data UtxoData = UtxoData - { _utxoDataAddress :: !Text, - _utxoDataAssets :: ![Asset], - _utxoDataDatum :: !(Maybe DatumOption), - _utxoDataIndex :: !Natural, - _utxoDataReferenceScript :: !(Maybe Script), - _utxoDataTxHash :: !Text, - _utxoDataSlot :: !SlotNo, - _utxoDataTxoutCbor :: !(Maybe (HexStringOf TxOutCbor)) - +data UtxoWithSlot = UtxoWithSlot + { _utxoWithSlotAddress :: !(Bech32StringOf Address), + -- ^ UTxO's address. + _utxoWithSlotAssets :: ![Asset], + -- ^ UTxO's assets. + _utxoWithSlotDatum :: !(Maybe DatumOption), + -- ^ UTxO's datum. + _utxoWithSlotIndex :: !TxIndex, + -- ^ UTxO's transaction index. + _utxoWithSlotReferenceScript :: !(Maybe Script), + -- ^ UTxO's script. + _utxoWithSlotTxHash :: !TxHash, + -- ^ UTxO's transaction hash. + _utxoWithSlotSlot :: !SlotNo, + -- ^ Absolute slot of block which produced the UTxO. + _utxoWithSlotTxoutCbor :: !(Maybe (HexStringOf TxOutCbor)) + -- ^ Hex encoded transaction output CBOR bytes. } deriving stock (Show, Eq, Ord, Generic) deriving (FromJSON, ToJSON) - via CustomJSON '[FieldLabelModifier '[StripPrefix "_utxoData", CamelToSnake]] UtxoData - --- | Convert @V1@ API version `UtxoData` type into corresponding @V0@ type. -v1UtxoToV0 :: UtxoData -> V0.Utxo -v1UtxoToV0 UtxoData {..} = V0.Utxo { - V0._utxoAddress = _utxoDataAddress - , V0._utxoAssets = map v1AssetToV0 _utxoDataAssets - , V0._utxoDatum = _utxoDataDatum - , V0._utxoIndex = _utxoDataIndex - , V0._utxoReferenceScript = _utxoDataReferenceScript - , V0._utxoTxHash = _utxoDataTxHash - , V0._utxoTxoutCbor = _utxoDataTxoutCbor + via CustomJSON '[FieldLabelModifier '[StripPrefix "_utxoWithSlot", CamelToSnake]] UtxoWithSlot + +-- | Convert @V1@ API version UTxO (with slot) type into corresponding @V0@ type. +v1UtxoWithSlotToV0 :: UtxoWithSlot -> V0.Utxo +v1UtxoWithSlotToV0 UtxoWithSlot {..} = V0.Utxo { + V0._utxoAddress = _utxoWithSlotAddress + , V0._utxoAssets = map v1AssetToV0 _utxoWithSlotAssets + , V0._utxoDatum = _utxoWithSlotDatum + , V0._utxoIndex = coerce _utxoWithSlotIndex + , V0._utxoReferenceScript = _utxoWithSlotReferenceScript + , V0._utxoTxHash = coerce _utxoWithSlotTxHash + , V0._utxoTxoutCbor = _utxoWithSlotTxoutCbor } --- | Transaction Outputs -data Utxos = Utxos - { _utxosData :: ![UtxoData], - _utxosLastUpdated :: !LastUpdated, - _utxosNextCursor :: !(Maybe Text) +-- | A paginated response of transaction outputs. +data PaginatedUtxoWithSlot = PaginatedUtxoWithSlot + { _paginatedUtxoWithSlotData :: ![UtxoWithSlot], + -- ^ List of UTxOs. + _paginatedUtxoWithSlotLastUpdated :: !LastUpdated, + -- ^ See `LastUpdated`. + _paginatedUtxoWithSlotNextCursor :: !(Maybe NextCursor) + -- ^ See `NextCursor` } deriving stock (Show, Eq, Generic) deriving (FromJSON, ToJSON) - via CustomJSON '[FieldLabelModifier '[StripPrefix "_utxos", CamelToSnake]] Utxos + via CustomJSON '[FieldLabelModifier '[StripPrefix "_paginatedUtxoWithSlot", CamelToSnake]] PaginatedUtxoWithSlot -instance HasCursor Utxos where - type CursorData Utxos = [UtxoData] - getNextCursor utxos = _utxosNextCursor utxos - getCursorData utxos = _utxosData utxos +instance HasCursor PaginatedUtxoWithSlot where + type CursorData PaginatedUtxoWithSlot = [UtxoWithSlot] + getNextCursor utxos = _paginatedUtxoWithSlotNextCursor utxos + getCursorData utxos = _paginatedUtxoWithSlotData utxos diff --git a/src/Maestro/Types/V1/Common/Pagination.hs b/src/Maestro/Types/V1/Common/Pagination.hs new file mode 100644 index 0000000..b3bbf1a --- /dev/null +++ b/src/Maestro/Types/V1/Common/Pagination.hs @@ -0,0 +1,27 @@ +-- | Module to define types demanded by cursor based pagination to be used by other types defined in @Maestro.Types.V1@. + +module Maestro.Types.V1.Common.Pagination ( + NextCursor (..) + , HasCursor (..) + ) where + +import Data.Aeson (FromJSON, ToJSON) +import Data.Kind (Type) +import Data.String (IsString) +import Data.Text (Text) +import GHC.Generics (Generic) +import Servant.API (FromHttpApiData, ToHttpApiData) + +-- | Type to denote for cursor to be returned in a paginated endpoint. +newtype NextCursor = NextCursor Text + deriving stock (Eq, Ord, Show, Generic) + deriving newtype (FromHttpApiData, ToHttpApiData, FromJSON, ToJSON, IsString) + +-- | Is the endpoint paged? +class (Monoid (CursorData a)) => HasCursor a where + -- | What is the type of the main data in question? + type CursorData a :: Type + -- | Get the next cursor from the value of the given type @a@. + getNextCursor :: a -> Maybe NextCursor + -- | Get the main data from the value of the given type @a@. + getCursorData :: a -> CursorData a diff --git a/src/Maestro/Types/V1/Datum.hs b/src/Maestro/Types/V1/Datum.hs new file mode 100644 index 0000000..913a497 --- /dev/null +++ b/src/Maestro/Types/V1/Datum.hs @@ -0,0 +1,20 @@ +-- | Module to define types for /\"Datum\"/ endpoints defined at [docs.gomaestro.org](https://docs.gomaestro.org/docs/category/datum). + +module Maestro.Types.V1.Datum + ( Datum (..) + ) where + +import Data.Aeson (Value) +import Data.Text (Text) +import Deriving.Aeson +import Maestro.Types.V1.Common (LowerFirst) + +-- | Details of datum when queried by it's hash. +data Datum = Datum + { _datumBytes :: !Text + -- ^ Hex encoded datum CBOR bytes. + , _datumJson :: !Value + -- ^ JSON representation of the datum. + } + deriving stock (Eq, Show, Generic) + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_datum", LowerFirst]] Datum diff --git a/src/Maestro/Types/V1/General.hs b/src/Maestro/Types/V1/General.hs index 4099dd4..04ca4df 100644 --- a/src/Maestro/Types/V1/General.hs +++ b/src/Maestro/Types/V1/General.hs @@ -1,4 +1,4 @@ --- | Module to define types for /\"General\"/ endpoints defined at [reference.gomaestro.org](https://reference.gomaestro.org/). +-- | Module to define types for /\"General\"/ endpoints defined at [docs.gomaestro.org](https://docs.gomaestro.org/docs/category/general). module Maestro.Types.V1.General ( -- * Types for @/system-start@ endpoint @@ -46,7 +46,9 @@ import Numeric.Natural (Natural) -- | Network start time since genesis. data SystemStart = SystemStart { _systemStartData :: !LocalTime + -- ^ Network start time since genesis. , _systemStartLastUpdated :: !LastUpdated + -- ^ See `LastUpdated`. } deriving stock (Eq, Ord, Show, Generic) deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_systemStart", CamelToSnake]] SystemStart @@ -58,7 +60,9 @@ data SystemStart = SystemStart -- | Network era summaries. data EraSummaries = EraSummaries { _eraSummariesData :: ![EraSummaryData] + -- ^ Era summaries, see `EraSummaryData`. , _eraSummariesLastUpdated :: !LastUpdated + -- ^ See `LastUpdated`. } deriving stock (Eq, Show, Generic) deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_eraSummaries", LowerFirst]] EraSummaries @@ -179,7 +183,9 @@ instance FromJSON MaestroRational where -- See `ProtocolParametersData`. data ProtocolParameters = ProtocolParameters { _protocolParametersData :: !ProtocolParametersData + -- ^ See `ProtocolParametersData`. , _protocolParametersLastUpdated :: !LastUpdated + -- ^ See `LastUpdated`. } deriving stock (Eq, Show, Generic) deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_protocolParameters", CamelToSnake]] ProtocolParameters @@ -254,7 +260,9 @@ data ChainTipData = ChainTipData -- | See `ChainTipData`. data ChainTip = ChainTip { _chainTipData :: !ChainTipData + -- ^ See `ChainTipData`. , _chainTipLastUpdated :: !LastUpdated + -- ^ See `LastUpdated`. } deriving stock (Eq, Show, Generic) deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_chainTip", CamelToSnake]] ChainTip diff --git a/src/Maestro/Types/V1/Pools.hs b/src/Maestro/Types/V1/Pools.hs new file mode 100644 index 0000000..e6a94df --- /dev/null +++ b/src/Maestro/Types/V1/Pools.hs @@ -0,0 +1,44 @@ +-- | Module to define types for /\"Pools\"/ category of endpoints defined at [docs.gomaestro.org](https://docs.gomaestro.org/docs/category/pools). + +module Maestro.Types.V1.Pools + ( PoolId, + PoolListInfo (..), + PaginatedPoolListInfo (..), + ) +where + +import Deriving.Aeson +import Maestro.Types.V1.Common + +-- | Phantom datatype to be used with, say `Bech32StringOf` to represent Bech32 representation of a pool id. +data PoolId + +-- | Information about a registered stake pool. +data PoolListInfo = PoolListInfo + { _poolListInfoPoolIdBech32 :: !(Bech32StringOf PoolId), + -- ^ Bech32 encoded Pool ID. + _poolListInfoTicker :: !(Maybe (TaggedText "pool-ticker")) + -- ^ Pool ticker symbol. + } + deriving stock (Show, Eq, Ord, Generic) + deriving + (FromJSON, ToJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "_poolListInfo", CamelToSnake]] PoolListInfo + +-- | Paginated list of registered stake pools. +data PaginatedPoolListInfo = PaginatedPoolListInfo + { _paginatedPoolListInfoData :: ![PoolListInfo] + -- ^ See `PoolListInfo`. + , _paginatedPoolListInfoLastUpdated :: !LastUpdated + -- ^ See `LastUpdated`. + , _paginatedPoolListInfoNextCursor :: !(Maybe NextCursor) + } + deriving stock (Show, Eq, Ord, Generic) + deriving + (FromJSON, ToJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "_paginatedPoolListInfo", CamelToSnake]] PaginatedPoolListInfo + +instance HasCursor PaginatedPoolListInfo where + type CursorData PaginatedPoolListInfo = [PoolListInfo] + getNextCursor pools = _paginatedPoolListInfoNextCursor pools + getCursorData pools = _paginatedPoolListInfoData pools diff --git a/src/Maestro/Types/V1/Transactions.hs b/src/Maestro/Types/V1/Transactions.hs new file mode 100644 index 0000000..330ba90 --- /dev/null +++ b/src/Maestro/Types/V1/Transactions.hs @@ -0,0 +1,80 @@ +-- | Module to define types for /\"Transactions\"/ category endpoints defined at [docs.gomaestro.org](https://docs.gomaestro.org/docs/category/transactions). + +module Maestro.Types.V1.Transactions + ( OutputReference (..) + , Utxo (..) + , v1UtxoToV0 + , PaginatedUtxo (..) + ) where + +import Data.Aeson (ToJSON (..), Value (..)) +import Data.Coerce (coerce) +import qualified Data.Text as T (pack) +import Deriving.Aeson +import Maestro.Types.Common +import qualified Maestro.Types.V0 as V0 (Utxo (..)) +import Maestro.Types.V1.Common +import Servant.API (ToHttpApiData (..)) + +-- | An UTxO output reference. +data OutputReference = OutputReference !TxHash !TxIndex + deriving stock (Show, Eq, Ord) + +instance ToHttpApiData OutputReference where + toQueryParam (OutputReference txHash txIndex) = coerce txHash <> T.pack (show txIndex) + +instance ToJSON OutputReference where + toJSON outputReference = String $ toQueryParam outputReference + +-- | Transaction output. +data Utxo = Utxo + { _utxoAddress :: !(Bech32StringOf Address), + -- ^ UTxO's address. + _utxoAssets :: ![Asset], + -- ^ UTxO's assets. + _utxoDatum :: !(Maybe DatumOption), + -- ^ UTxO's datum. + _utxoIndex :: !TxIndex, + -- ^ UTxO's transaction index. + _utxoReferenceScript :: !(Maybe Script), + -- ^ UTxO's script. + _utxoTxHash :: !TxHash, + -- ^ UTxO's transaction hash. + _utxoTxoutCbor :: !(Maybe (HexStringOf TxOutCbor)) + -- ^ Hex encoded transaction output CBOR bytes. + } + deriving stock (Show, Eq, Ord, Generic) + deriving + (FromJSON, ToJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "_utxo", CamelToSnake]] Utxo + +-- | Convert @V1@ API version UTxO type into corresponding @V0@ type. +v1UtxoToV0 :: Utxo -> V0.Utxo +v1UtxoToV0 Utxo {..} = V0.Utxo { + V0._utxoAddress = _utxoAddress + , V0._utxoAssets = map v1AssetToV0 _utxoAssets + , V0._utxoDatum = _utxoDatum + , V0._utxoIndex = coerce _utxoIndex + , V0._utxoReferenceScript = _utxoReferenceScript + , V0._utxoTxHash = coerce _utxoTxHash + , V0._utxoTxoutCbor = _utxoTxoutCbor + } + +-- | A paginated response of transaction outputs. +data PaginatedUtxo = PaginatedUtxo + { _paginatedUtxoData :: ![Utxo], + -- ^ List of UTxOs. + _paginatedUtxoLastUpdated :: !LastUpdated, + -- ^ See `LastUpdated`. + _paginatedUtxoNextCursor :: !(Maybe NextCursor) + -- ^ See `NextCursor` + } + deriving stock (Show, Eq, Generic) + deriving + (FromJSON, ToJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "_paginatedUtxo", CamelToSnake]] PaginatedUtxo + +instance HasCursor PaginatedUtxo where + type CursorData PaginatedUtxo = [Utxo] + getNextCursor utxos = _paginatedUtxoNextCursor utxos + getCursorData utxos = _paginatedUtxoData utxos From 0a40d86b0f361e797d7d4d234e3cbf248051b7d7 Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Sun, 9 Jul 2023 22:04:56 +0530 Subject: [PATCH 11/24] Feat 30: V1 Endpoints support - support for endpoints needed for Atlas --- src/Maestro/API/V1/Addresses.hs | 7 ------- test/Maestro/Test/Transaction.hs | 1 + 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Maestro/API/V1/Addresses.hs b/src/Maestro/API/V1/Addresses.hs index 84071f4..8fde702 100644 --- a/src/Maestro/API/V1/Addresses.hs +++ b/src/Maestro/API/V1/Addresses.hs @@ -22,11 +22,4 @@ data AddressesAPI route = AddressesAPI :> ReqBody '[JSON] [Bech32StringOf Address] :> Post '[JSON] PaginatedUtxoWithSlot - -- , _addressUtxoRefs - -- :: route - -- :- Capture "address" Text - -- :> "utxo_refs" - -- :> Pagination - -- :> Get '[JSON] [UtxoRef] - } deriving (Generic) diff --git a/test/Maestro/Test/Transaction.hs b/test/Maestro/Test/Transaction.hs index cbb58b2..56be7f6 100644 --- a/test/Maestro/Test/Transaction.hs +++ b/test/Maestro/Test/Transaction.hs @@ -107,4 +107,5 @@ txUtxoExpected = , _scriptType = PlutusV2 , _scriptJson = Nothing } + , _utxoTxoutCbor = Nothing } From a46e05ff7722f78abeda974e5f63856bdbf5d319 Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Sun, 9 Jul 2023 22:12:05 +0530 Subject: [PATCH 12/24] Feat 30: V1 Endpoints support - support for endpoints needed for Atlas --- src/Maestro/Types/V1/General.hs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Maestro/Types/V1/General.hs b/src/Maestro/Types/V1/General.hs index 04ca4df..70327fd 100644 --- a/src/Maestro/Types/V1/General.hs +++ b/src/Maestro/Types/V1/General.hs @@ -5,7 +5,7 @@ module Maestro.Types.V1.General SystemStart (..) -- * Types for @/era-history@ endpoint , EraSummaries (..) - , EraSummaryData (..) + , EraSummary (..) , EraParameters (..) , EraBound (..) -- * Types for @/protocol-params@ endpoint @@ -59,8 +59,8 @@ data SystemStart = SystemStart -- | Network era summaries. data EraSummaries = EraSummaries - { _eraSummariesData :: ![EraSummaryData] - -- ^ Era summaries, see `EraSummaryData`. + { _eraSummariesData :: ![EraSummary] + -- ^ Era summaries, see `EraSummary`. , _eraSummariesLastUpdated :: !LastUpdated -- ^ See `LastUpdated`. } @@ -68,7 +68,7 @@ data EraSummaries = EraSummaries deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_eraSummaries", LowerFirst]] EraSummaries -- | Network era summary. -data EraSummaryData = EraSummaryData +data EraSummary = EraSummary { _eraSummaryDataStart :: !EraBound -- ^ Start of this era. , _eraSummaryDataEnd :: !(Maybe EraBound) @@ -77,7 +77,7 @@ data EraSummaryData = EraSummaryData -- ^ Parameters of this era. } deriving stock (Eq, Show, Generic) - deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_eraSummaryData", LowerFirst]] EraSummaryData + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_eraSummaryData", LowerFirst]] EraSummary -- | Parameters for a network era which can vary between hardforks. data EraParameters = EraParameters From c298bef3e5945349ad83a90c8a2ada7c4ce9e012 Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Mon, 10 Jul 2023 08:58:04 +0530 Subject: [PATCH 13/24] Feat 30: V1 Endpoints support - support for endpoints needed for Atlas - IsUtxo typeclass --- src/Maestro/Types/V1/Common.hs | 20 +++++++++++ src/Maestro/Types/V1/Transactions.hs | 50 ++++++++++++++++------------ 2 files changed, 49 insertions(+), 21 deletions(-) diff --git a/src/Maestro/Types/V1/Common.hs b/src/Maestro/Types/V1/Common.hs index c87af4a..6a9df7d 100644 --- a/src/Maestro/Types/V1/Common.hs +++ b/src/Maestro/Types/V1/Common.hs @@ -6,8 +6,11 @@ module Maestro.Types.V1.Common RewardAddress, TaggedText (..), LastUpdated (..), + NonAdaNativeToken (..), + AssetUnit (..), Asset (..), v1AssetToV0, + IsUtxo (..), UtxoWithSlot (..), v1UtxoWithSlotToV0, PaginatedUtxoWithSlot (..), @@ -104,6 +107,15 @@ v1AssetToV0 Asset {..} = V0.Asset { UserMintedToken (NonAdaNativeToken policyId tokenName) -> coerce policyId <> "#" <> coerce tokenName } +-- | To get basic details from an UTxO. +class IsUtxo a where + getAddress :: a -> Bech32StringOf Address + getAssets :: a -> [Asset] + getDatum :: a -> Maybe DatumOption + getTxHash :: a -> TxHash + getIndex :: a -> TxIndex + getReferenceScript :: a -> Maybe Script + -- | Transaction output. data UtxoWithSlot = UtxoWithSlot { _utxoWithSlotAddress :: !(Bech32StringOf Address), @@ -128,6 +140,14 @@ data UtxoWithSlot = UtxoWithSlot (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_utxoWithSlot", CamelToSnake]] UtxoWithSlot +instance IsUtxo UtxoWithSlot where + getAddress = _utxoWithSlotAddress + getAssets = _utxoWithSlotAssets + getDatum = _utxoWithSlotDatum + getTxHash = _utxoWithSlotTxHash + getIndex = _utxoWithSlotIndex + getReferenceScript = _utxoWithSlotReferenceScript + -- | Convert @V1@ API version UTxO (with slot) type into corresponding @V0@ type. v1UtxoWithSlotToV0 :: UtxoWithSlot -> V0.Utxo v1UtxoWithSlotToV0 UtxoWithSlot {..} = V0.Utxo { diff --git a/src/Maestro/Types/V1/Transactions.hs b/src/Maestro/Types/V1/Transactions.hs index 330ba90..49362de 100644 --- a/src/Maestro/Types/V1/Transactions.hs +++ b/src/Maestro/Types/V1/Transactions.hs @@ -2,7 +2,7 @@ module Maestro.Types.V1.Transactions ( OutputReference (..) - , Utxo (..) + , UtxoWithBytes (..) , v1UtxoToV0 , PaginatedUtxo (..) ) where @@ -27,42 +27,50 @@ instance ToJSON OutputReference where toJSON outputReference = String $ toQueryParam outputReference -- | Transaction output. -data Utxo = Utxo - { _utxoAddress :: !(Bech32StringOf Address), +data UtxoWithBytes = UtxoWithBytes + { _utxoWithBytesAddress :: !(Bech32StringOf Address), -- ^ UTxO's address. - _utxoAssets :: ![Asset], + _utxoWithBytesAssets :: ![Asset], -- ^ UTxO's assets. - _utxoDatum :: !(Maybe DatumOption), + _utxoWithBytesDatum :: !(Maybe DatumOption), -- ^ UTxO's datum. - _utxoIndex :: !TxIndex, + _utxoWithBytesIndex :: !TxIndex, -- ^ UTxO's transaction index. - _utxoReferenceScript :: !(Maybe Script), + _utxoWithBytesReferenceScript :: !(Maybe Script), -- ^ UTxO's script. - _utxoTxHash :: !TxHash, + _utxoWithBytesTxHash :: !TxHash, -- ^ UTxO's transaction hash. - _utxoTxoutCbor :: !(Maybe (HexStringOf TxOutCbor)) + _utxoWithBytesTxoutCbor :: !(Maybe (HexStringOf TxOutCbor)) -- ^ Hex encoded transaction output CBOR bytes. } deriving stock (Show, Eq, Ord, Generic) deriving (FromJSON, ToJSON) - via CustomJSON '[FieldLabelModifier '[StripPrefix "_utxo", CamelToSnake]] Utxo + via CustomJSON '[FieldLabelModifier '[StripPrefix "_utxoWithBytes", CamelToSnake]] UtxoWithBytes + +instance IsUtxo UtxoWithBytes where + getAddress = _utxoWithBytesAddress + getAssets = _utxoWithBytesAssets + getDatum = _utxoWithBytesDatum + getTxHash = _utxoWithBytesTxHash + getIndex = _utxoWithBytesIndex + getReferenceScript = _utxoWithBytesReferenceScript -- | Convert @V1@ API version UTxO type into corresponding @V0@ type. -v1UtxoToV0 :: Utxo -> V0.Utxo -v1UtxoToV0 Utxo {..} = V0.Utxo { - V0._utxoAddress = _utxoAddress - , V0._utxoAssets = map v1AssetToV0 _utxoAssets - , V0._utxoDatum = _utxoDatum - , V0._utxoIndex = coerce _utxoIndex - , V0._utxoReferenceScript = _utxoReferenceScript - , V0._utxoTxHash = coerce _utxoTxHash - , V0._utxoTxoutCbor = _utxoTxoutCbor +v1UtxoToV0 :: UtxoWithBytes -> V0.Utxo +v1UtxoToV0 UtxoWithBytes {..} = V0.Utxo { + V0._utxoAddress = _utxoWithBytesAddress + , V0._utxoAssets = map v1AssetToV0 _utxoWithBytesAssets + , V0._utxoDatum = _utxoWithBytesDatum + , V0._utxoIndex = coerce _utxoWithBytesIndex + , V0._utxoReferenceScript = _utxoWithBytesReferenceScript + , V0._utxoTxHash = coerce _utxoWithBytesTxHash + , V0._utxoTxoutCbor = _utxoWithBytesTxoutCbor } -- | A paginated response of transaction outputs. data PaginatedUtxo = PaginatedUtxo - { _paginatedUtxoData :: ![Utxo], + { _paginatedUtxoData :: ![UtxoWithBytes], -- ^ List of UTxOs. _paginatedUtxoLastUpdated :: !LastUpdated, -- ^ See `LastUpdated`. @@ -75,6 +83,6 @@ data PaginatedUtxo = PaginatedUtxo via CustomJSON '[FieldLabelModifier '[StripPrefix "_paginatedUtxo", CamelToSnake]] PaginatedUtxo instance HasCursor PaginatedUtxo where - type CursorData PaginatedUtxo = [Utxo] + type CursorData PaginatedUtxo = [UtxoWithBytes] getNextCursor utxos = _paginatedUtxoNextCursor utxos getCursorData utxos = _paginatedUtxoData utxos From 926e7655e0a2f7d50fa8a10ea30b261651277423 Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Mon, 10 Jul 2023 09:09:06 +0530 Subject: [PATCH 14/24] Feat 30: V1 Endpoints support - support for endpoints needed for Atlas - improved naming for NID so as to avoid conflicts --- src/Maestro/Types/V1/Addresses.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Maestro/Types/V1/Addresses.hs b/src/Maestro/Types/V1/Addresses.hs index 76c208c..bd89e63 100644 --- a/src/Maestro/Types/V1/Addresses.hs +++ b/src/Maestro/Types/V1/Addresses.hs @@ -21,9 +21,9 @@ import Servant.API (FromHttpApiData, ToHttpApiData) type AddressToDecode = "Bech32/Hex/Base58 encoded address" -- | Denotes network for the entity in question, such as address. -data NetworkId = Mainnet | Testnet +data NetworkId = NIDMainnet | NIDTestnet deriving stock (Show, Eq, Ord, Generic) - deriving (FromJSON, ToJSON) via CustomJSON '[ConstructorTagModifier '[LowerFirst]] NetworkId + deriving (FromJSON, ToJSON) via CustomJSON '[ConstructorTagModifier '[StripPrefix "NID", LowerFirst]] NetworkId -- | Denotes kind of a payment credential. data PaymentCredKind = PCKKey | PCKScript From 203be523a27f1d56b646f244a1afc8271ce2b7ba Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Mon, 10 Jul 2023 09:11:12 +0530 Subject: [PATCH 15/24] Feat 30: V1 Endpoints support - support for endpoints needed for Atlas - exported clients --- src/Maestro/Client/V1.hs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Maestro/Client/V1.hs b/src/Maestro/Client/V1.hs index f86018f..265cc3d 100644 --- a/src/Maestro/Client/V1.hs +++ b/src/Maestro/Client/V1.hs @@ -3,6 +3,11 @@ module Maestro.Client.V1 , module Maestro.Client.Error , module Maestro.Client.V1.Core , module Maestro.Client.V1.Addresses + , module Maestro.Client.V1.Datum + , module Maestro.Client.V1.General + , module Maestro.Client.V1.Pools + , module Maestro.Client.V1.Transactions + , module Maestro.Client.V1.TxManager ) where @@ -10,3 +15,8 @@ import Maestro.Client.Env import Maestro.Client.Error import Maestro.Client.V1.Addresses import Maestro.Client.V1.Core +import Maestro.Client.V1.Datum +import Maestro.Client.V1.General +import Maestro.Client.V1.Pools +import Maestro.Client.V1.Transactions +import Maestro.Client.V1.TxManager From 373266adee66409a72d1e470314c51713c3f0fd8 Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Mon, 10 Jul 2023 09:36:59 +0530 Subject: [PATCH 16/24] Feat 30: V1 Endpoints support - support for endpoints needed for Atlas - endpoint to query for utxo refs at an address --- src/Maestro/API/V1/Addresses.hs | 7 +++++++ src/Maestro/Client/V1/Addresses.hs | 14 +++++++++++++- src/Maestro/Types/V1/Addresses.hs | 29 +++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/Maestro/API/V1/Addresses.hs b/src/Maestro/API/V1/Addresses.hs index 8fde702..6f8483d 100644 --- a/src/Maestro/API/V1/Addresses.hs +++ b/src/Maestro/API/V1/Addresses.hs @@ -22,4 +22,11 @@ data AddressesAPI route = AddressesAPI :> ReqBody '[JSON] [Bech32StringOf Address] :> Post '[JSON] PaginatedUtxoWithSlot + , _addressUtxoRefs + :: route + :- Capture "address" (Bech32StringOf Address) + :> "utxo_refs" + :> Pagination + :> Get '[JSON] PaginatedOutputReferenceObject + } deriving (Generic) diff --git a/src/Maestro/Client/V1/Addresses.hs b/src/Maestro/Client/V1/Addresses.hs index f6fa1c9..3004fe4 100644 --- a/src/Maestro/Client/V1/Addresses.hs +++ b/src/Maestro/Client/V1/Addresses.hs @@ -2,6 +2,7 @@ module Maestro.Client.V1.Addresses ( utxosAtMultiAddresses, + getRefsAtAddress, ) where import Maestro.API.V1 @@ -9,7 +10,8 @@ import Maestro.API.V1.Addresses import Maestro.Client.Env import Maestro.Client.V1.Core import Maestro.Types.Common (Address, Bech32StringOf) -import Maestro.Types.V1 (PaginatedUtxoWithSlot) +import Maestro.Types.V1 (PaginatedOutputReferenceObject, + PaginatedUtxoWithSlot) import Servant.API.Generic import Servant.Client @@ -30,3 +32,13 @@ utxosAtMultiAddresses :: [Bech32StringOf Address] -> IO PaginatedUtxoWithSlot utxosAtMultiAddresses = _addressesUtxos . addressClient + +-- | UTxO IDs for all the unspent transaction outputs at an address. +getRefsAtAddress :: + MaestroEnv 'V1 -> + -- | The Address in Bech32 format. + Bech32StringOf Address -> + -- | The pagination attributes + Cursor -> + IO PaginatedOutputReferenceObject +getRefsAtAddress = _addressUtxoRefs . addressClient diff --git a/src/Maestro/Types/V1/Addresses.hs b/src/Maestro/Types/V1/Addresses.hs index bd89e63..6304436 100644 --- a/src/Maestro/Types/V1/Addresses.hs +++ b/src/Maestro/Types/V1/Addresses.hs @@ -10,6 +10,8 @@ module Maestro.Types.V1.Addresses ( ChainPointer (..), StakingCredential (..), AddressInfo (..), + OutputReferenceObject (..), + PaginatedOutputReferenceObject (..), ) where import Deriving.Aeson @@ -99,3 +101,30 @@ data AddressInfo = AddressInfo deriving stock (Show, Eq, Ord, Generic) deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_addressInfo", CamelToSnake]] AddressInfo + +-- | Output reference of an UTxO. This is different from `OutputReference` type as later JSON representation is a string whereas this has an object format. +data OutputReferenceObject = OutputReferenceObject + { _outputReferenceObjectIndex :: !TxIndex + , _outputReferenceObjectTxHash :: !TxHash + } + deriving stock (Show, Eq, Generic) + deriving (FromJSON, ToJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "_outputReferenceObject", CamelToSnake]] OutputReferenceObject + +-- | UTxO IDs for all the unspent transaction outputs at an address. +data PaginatedOutputReferenceObject = PaginatedOutputReferenceObject + { _paginatedOutputReferenceObjectData :: ![OutputReferenceObject] + -- ^ See `OutputReferenceObject`. + , _paginatedOutputReferenceObjectLastUpdated :: !LastUpdated + -- ^ See `LastUpdated`. + , _paginatedOutputReferenceObjectNextCursor :: !(Maybe NextCursor) + -- ^ See `NextCursor`. + } + deriving stock (Show, Eq, Generic) + deriving (FromJSON, ToJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "_paginatedOutputReferenceObject", CamelToSnake]] PaginatedOutputReferenceObject + +instance HasCursor PaginatedOutputReferenceObject where + type CursorData PaginatedOutputReferenceObject = [OutputReferenceObject] + getNextCursor orefs = _paginatedOutputReferenceObjectNextCursor orefs + getCursorData orefs = _paginatedOutputReferenceObjectData orefs From 8e0d799bdfcd37da9ed2609fcc0c93e3a02f862c Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Mon, 10 Jul 2023 09:48:22 +0530 Subject: [PATCH 17/24] Feat 30: V1 Endpoints support - support for endpoints needed for Atlas - changed record fields for era summary --- src/Maestro/Types/V1/General.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Maestro/Types/V1/General.hs b/src/Maestro/Types/V1/General.hs index 70327fd..980ca34 100644 --- a/src/Maestro/Types/V1/General.hs +++ b/src/Maestro/Types/V1/General.hs @@ -69,15 +69,15 @@ data EraSummaries = EraSummaries -- | Network era summary. data EraSummary = EraSummary - { _eraSummaryDataStart :: !EraBound + { _eraSummaryStart :: !EraBound -- ^ Start of this era. - , _eraSummaryDataEnd :: !(Maybe EraBound) + , _eraSummaryEnd :: !(Maybe EraBound) -- ^ End of this era. - , _eraSummaryDataParameters :: !EraParameters + , _eraSummaryParameters :: !EraParameters -- ^ Parameters of this era. } deriving stock (Eq, Show, Generic) - deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_eraSummaryData", LowerFirst]] EraSummary + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_eraSummary", LowerFirst]] EraSummary -- | Parameters for a network era which can vary between hardforks. data EraParameters = EraParameters From 642d09f82c348e2621509bb33d8988be49747040 Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Mon, 10 Jul 2023 11:52:21 +0530 Subject: [PATCH 18/24] Feat 30: V1 Endpoints support - support for endpoints needed for Atlas - bug fixes --- src/Maestro/Types/V1/General.hs | 2 +- src/Maestro/Types/V1/Transactions.hs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Maestro/Types/V1/General.hs b/src/Maestro/Types/V1/General.hs index 980ca34..7bfb0dd 100644 --- a/src/Maestro/Types/V1/General.hs +++ b/src/Maestro/Types/V1/General.hs @@ -65,7 +65,7 @@ data EraSummaries = EraSummaries -- ^ See `LastUpdated`. } deriving stock (Eq, Show, Generic) - deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_eraSummaries", LowerFirst]] EraSummaries + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_eraSummaries", CamelToSnake]] EraSummaries -- | Network era summary. data EraSummary = EraSummary diff --git a/src/Maestro/Types/V1/Transactions.hs b/src/Maestro/Types/V1/Transactions.hs index 49362de..b4a0af6 100644 --- a/src/Maestro/Types/V1/Transactions.hs +++ b/src/Maestro/Types/V1/Transactions.hs @@ -21,7 +21,7 @@ data OutputReference = OutputReference !TxHash !TxIndex deriving stock (Show, Eq, Ord) instance ToHttpApiData OutputReference where - toQueryParam (OutputReference txHash txIndex) = coerce txHash <> T.pack (show txIndex) + toQueryParam (OutputReference txHash txIndex) = coerce txHash <> "#" <> T.pack (show txIndex) instance ToJSON OutputReference where toJSON outputReference = String $ toQueryParam outputReference From 73f55260dc3b7deaed459f5c418c4a73c790048c Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Mon, 10 Jul 2023 13:29:20 +0530 Subject: [PATCH 19/24] Feat 30: V1 Endpoints support - support for endpoints needed for Atlas - IsTimestamped typeclass with it's associated type family --- maestro-sdk.cabal | 1 + src/Maestro/API/V1/Datum.hs | 2 +- src/Maestro/API/V1/General.hs | 8 +- src/Maestro/API/V1/Pools.hs | 2 +- src/Maestro/Client/V1/Core/Pagination.hs | 6 +- src/Maestro/Client/V1/Datum.hs | 2 +- src/Maestro/Client/V1/General.hs | 8 +- src/Maestro/Types/V1/Addresses.hs | 9 +- src/Maestro/Types/V1/Common.hs | 47 ++++---- src/Maestro/Types/V1/Common/Pagination.hs | 19 ++- src/Maestro/Types/V1/Common/Timestamped.hs | 29 +++++ src/Maestro/Types/V1/Datum.hs | 19 ++- src/Maestro/Types/V1/General.hs | 127 ++++++++++++--------- src/Maestro/Types/V1/Pools.hs | 9 +- src/Maestro/Types/V1/Transactions.hs | 9 +- 15 files changed, 183 insertions(+), 114 deletions(-) create mode 100644 src/Maestro/Types/V1/Common/Timestamped.hs diff --git a/maestro-sdk.cabal b/maestro-sdk.cabal index 522432a..4189f4d 100644 --- a/maestro-sdk.cabal +++ b/maestro-sdk.cabal @@ -107,6 +107,7 @@ library Maestro.Types.V1.Datum Maestro.Types.V1.Common Maestro.Types.V1.Common.Pagination + Maestro.Types.V1.Common.Timestamped Maestro.Types.V1.General Maestro.Types.V1.Pools Maestro.Types.V1.Transactions diff --git a/src/Maestro/API/V1/Datum.hs b/src/Maestro/API/V1/Datum.hs index 62cb273..5054937 100644 --- a/src/Maestro/API/V1/Datum.hs +++ b/src/Maestro/API/V1/Datum.hs @@ -10,5 +10,5 @@ newtype DatumAPI route = _datumByHash :: route :- Capture "datum_hash" (HexStringOf DatumHash) - :> Get '[JSON] Datum + :> Get '[JSON] TimestampedDatum } deriving Generic diff --git a/src/Maestro/API/V1/General.hs b/src/Maestro/API/V1/General.hs index 82093ce..2755af3 100644 --- a/src/Maestro/API/V1/General.hs +++ b/src/Maestro/API/V1/General.hs @@ -10,17 +10,17 @@ data GeneralAPI route = _systemStart :: route :- "system-start" - :> Get '[JSON] SystemStart + :> Get '[JSON] TimestampedSystemStart , _eraHistory :: route :- "era-history" - :> Get '[JSON] EraSummaries + :> Get '[JSON] TimestampedEraSummaries , _protocolParams :: route :- "protocol-params" - :> Get '[JSON] ProtocolParameters + :> Get '[JSON] TimestampedProtocolParameters , _chainTip :: route :- "chain-tip" - :> Get '[JSON] ChainTip + :> Get '[JSON] TimestampedChainTip } deriving Generic diff --git a/src/Maestro/API/V1/Pools.hs b/src/Maestro/API/V1/Pools.hs index 21b1be4..960a899 100644 --- a/src/Maestro/API/V1/Pools.hs +++ b/src/Maestro/API/V1/Pools.hs @@ -5,7 +5,7 @@ import Maestro.Types.V1 import Servant.API import Servant.API.Generic -data PoolsAPI route = PoolsAPI +newtype PoolsAPI route = PoolsAPI { _listPools :: route :- Pagination diff --git a/src/Maestro/Client/V1/Core/Pagination.hs b/src/Maestro/Client/V1/Core/Pagination.hs index 1558cb5..6d918c4 100644 --- a/src/Maestro/Client/V1/Core/Pagination.hs +++ b/src/Maestro/Client/V1/Core/Pagination.hs @@ -3,6 +3,8 @@ module Maestro.Client.V1.Core.Pagination where import Data.Default.Class import Data.Maybe (isNothing) import Data.Proxy (Proxy (..)) +import Maestro.Types.V1.Common (IsTimestamped (getTimestampedData), + TimestampedData) import Maestro.Types.V1.Common.Pagination import Servant.API (QueryParam, (:>)) import Servant.Client.Core (Client, HasClient, @@ -23,13 +25,13 @@ instance Default Cursor where def = Cursor maxResultsPerPage Nothing -- Utility for querying all results from a paged endpoint. -allPages :: (Monad m, HasCursor a) => (Cursor -> m a) -> m (CursorData a) +allPages :: (Monad m, HasCursor a) => (Cursor -> m a) -> m (TimestampedData a) allPages act = fetch Nothing where fetch cursor = do xs <- act $ Cursor maxResultsPerPage cursor let nextCursor = getNextCursor xs - cursorData = getCursorData xs + cursorData = getTimestampedData xs if isNothing nextCursor then pure cursorData else do diff --git a/src/Maestro/Client/V1/Datum.hs b/src/Maestro/Client/V1/Datum.hs index 8c369be..b190d21 100644 --- a/src/Maestro/Client/V1/Datum.hs +++ b/src/Maestro/Client/V1/Datum.hs @@ -16,5 +16,5 @@ datumClient :: MaestroEnv 'V1 -> DatumAPI (AsClientT IO) datumClient = fromServant . _datum . apiV1Client -- | Get information about the datum from it's hash. -getDatumByHash :: MaestroEnv 'V1 -> HexStringOf DatumHash -> IO Datum +getDatumByHash :: MaestroEnv 'V1 -> HexStringOf DatumHash -> IO TimestampedDatum getDatumByHash = _datumByHash . datumClient diff --git a/src/Maestro/Client/V1/General.hs b/src/Maestro/Client/V1/General.hs index 59a7579..4a90b89 100644 --- a/src/Maestro/Client/V1/General.hs +++ b/src/Maestro/Client/V1/General.hs @@ -19,17 +19,17 @@ generalClient :: MaestroEnv 'V1 -> GeneralAPI (AsClientT IO) generalClient = fromServant . _general . apiV1Client -- | Get details about the latest block of the network. -getChainTip :: MaestroEnv 'V1 -> IO ChainTip +getChainTip :: MaestroEnv 'V1 -> IO TimestampedChainTip getChainTip = _chainTip . generalClient -- | Get network start time since genesis. -getSystemStart :: MaestroEnv 'V1 -> IO SystemStart +getSystemStart :: MaestroEnv 'V1 -> IO TimestampedSystemStart getSystemStart = _systemStart . generalClient -- | Get network era history. -getEraHistory :: MaestroEnv 'V1 -> IO EraSummaries +getEraHistory :: MaestroEnv 'V1 -> IO TimestampedEraSummaries getEraHistory = _eraHistory . generalClient -- | Get protocol parameters for the latest epoch. -getProtocolParameters :: MaestroEnv 'V1 -> IO ProtocolParameters +getProtocolParameters :: MaestroEnv 'V1 -> IO TimestampedProtocolParameters getProtocolParameters = _protocolParams . generalClient diff --git a/src/Maestro/Types/V1/Addresses.hs b/src/Maestro/Types/V1/Addresses.hs index 6304436..1ea8332 100644 --- a/src/Maestro/Types/V1/Addresses.hs +++ b/src/Maestro/Types/V1/Addresses.hs @@ -124,7 +124,10 @@ data PaginatedOutputReferenceObject = PaginatedOutputReferenceObject deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_paginatedOutputReferenceObject", CamelToSnake]] PaginatedOutputReferenceObject +instance IsTimestamped PaginatedOutputReferenceObject where + type TimestampedData PaginatedOutputReferenceObject = [OutputReferenceObject] + getTimestampedData = _paginatedOutputReferenceObjectData + getTimestamp = _paginatedOutputReferenceObjectLastUpdated + instance HasCursor PaginatedOutputReferenceObject where - type CursorData PaginatedOutputReferenceObject = [OutputReferenceObject] - getNextCursor orefs = _paginatedOutputReferenceObjectNextCursor orefs - getCursorData orefs = _paginatedOutputReferenceObjectData orefs + getNextCursor = _paginatedOutputReferenceObjectNextCursor diff --git a/src/Maestro/Types/V1/Common.hs b/src/Maestro/Types/V1/Common.hs index 6a9df7d..d1545bf 100644 --- a/src/Maestro/Types/V1/Common.hs +++ b/src/Maestro/Types/V1/Common.hs @@ -5,7 +5,6 @@ module Maestro.Types.V1.Common StakingCredentialAddress, RewardAddress, TaggedText (..), - LastUpdated (..), NonAdaNativeToken (..), AssetUnit (..), Asset (..), @@ -15,23 +14,26 @@ module Maestro.Types.V1.Common v1UtxoWithSlotToV0, PaginatedUtxoWithSlot (..), module Maestro.Types.Common, - module Maestro.Types.V1.Common.Pagination + module Maestro.Types.V1.Common.Pagination, + module Maestro.Types.V1.Common.Timestamped ) where -import Data.Aeson (FromJSON (..), ToJSON (..), - Value (..), withText) -import Data.Coerce (coerce) -import Data.String (IsString) -import Data.Text (Text) -import qualified Data.Text as T (splitAt) +import Data.Aeson (FromJSON (..), + ToJSON (..), Value (..), + withText) +import Data.Coerce (coerce) +import Data.String (IsString) +import Data.Text (Text) +import qualified Data.Text as T (splitAt) import Deriving.Aeson -import GHC.TypeLits (Symbol) +import GHC.TypeLits (Symbol) import Maestro.Types.Common -import qualified Maestro.Types.V0 as V0 (Asset (..), - Utxo (..)) +import qualified Maestro.Types.V0 as V0 (Asset (..), + Utxo (..)) import Maestro.Types.V1.Common.Pagination -import Servant.API (FromHttpApiData (..), - ToHttpApiData (..)) +import Maestro.Types.V1.Common.Timestamped +import Servant.API (FromHttpApiData (..), + ToHttpApiData (..)) -- | Phantom datatype to be used with, say `Bech32StringOf` to represent Bech32 representation of payment credential of an address. data PaymentCredentialAddress @@ -47,16 +49,6 @@ newtype TaggedText (description :: Symbol) = TaggedText Text deriving stock (Eq, Ord, Show, Generic) deriving newtype (FromHttpApiData, ToHttpApiData, FromJSON, ToJSON, IsString) --- | Details of the most recent block processed by the indexer (aka chain tip); that is, the data returned is correct as of this block in time. -data LastUpdated = LastUpdated - { _lastUpdatedBlockHash :: !BlockHash - -- ^ Hash of the latest block. - , _lastUpdatedBlockSlot :: !SlotNo - -- ^ Slot number for the tip. - } - deriving stock (Eq, Ord, Show, Generic) - deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_lastUpdated", CamelToSnake]] LastUpdated - -- | Type to denote for native tokens (besides ada). data NonAdaNativeToken = NonAdaNativeToken !PolicyId !TokenName deriving stock (Eq, Ord, Show) @@ -174,7 +166,10 @@ data PaginatedUtxoWithSlot = PaginatedUtxoWithSlot (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_paginatedUtxoWithSlot", CamelToSnake]] PaginatedUtxoWithSlot +instance IsTimestamped PaginatedUtxoWithSlot where + type TimestampedData PaginatedUtxoWithSlot = [UtxoWithSlot] + getTimestampedData = _paginatedUtxoWithSlotData + getTimestamp = _paginatedUtxoWithSlotLastUpdated + instance HasCursor PaginatedUtxoWithSlot where - type CursorData PaginatedUtxoWithSlot = [UtxoWithSlot] - getNextCursor utxos = _paginatedUtxoWithSlotNextCursor utxos - getCursorData utxos = _paginatedUtxoWithSlotData utxos + getNextCursor = _paginatedUtxoWithSlotNextCursor diff --git a/src/Maestro/Types/V1/Common/Pagination.hs b/src/Maestro/Types/V1/Common/Pagination.hs index b3bbf1a..75e7968 100644 --- a/src/Maestro/Types/V1/Common/Pagination.hs +++ b/src/Maestro/Types/V1/Common/Pagination.hs @@ -5,12 +5,13 @@ module Maestro.Types.V1.Common.Pagination ( , HasCursor (..) ) where -import Data.Aeson (FromJSON, ToJSON) -import Data.Kind (Type) -import Data.String (IsString) -import Data.Text (Text) -import GHC.Generics (Generic) -import Servant.API (FromHttpApiData, ToHttpApiData) +import Data.Aeson (FromJSON, ToJSON) +import Data.String (IsString) +import Data.Text (Text) +import GHC.Generics (Generic) +import Maestro.Types.V1.Common.Timestamped +import Servant.API (FromHttpApiData, + ToHttpApiData) -- | Type to denote for cursor to be returned in a paginated endpoint. newtype NextCursor = NextCursor Text @@ -18,10 +19,6 @@ newtype NextCursor = NextCursor Text deriving newtype (FromHttpApiData, ToHttpApiData, FromJSON, ToJSON, IsString) -- | Is the endpoint paged? -class (Monoid (CursorData a)) => HasCursor a where - -- | What is the type of the main data in question? - type CursorData a :: Type +class (IsTimestamped a, Monoid (TimestampedData a)) => HasCursor a where -- | Get the next cursor from the value of the given type @a@. getNextCursor :: a -> Maybe NextCursor - -- | Get the main data from the value of the given type @a@. - getCursorData :: a -> CursorData a diff --git a/src/Maestro/Types/V1/Common/Timestamped.hs b/src/Maestro/Types/V1/Common/Timestamped.hs new file mode 100644 index 0000000..76c8e3c --- /dev/null +++ b/src/Maestro/Types/V1/Common/Timestamped.hs @@ -0,0 +1,29 @@ +-- | Module to define typeclass for timestamped response, i.e. response which has a @data@ & @last_updated@ field. + +module Maestro.Types.V1.Common.Timestamped ( + LastUpdated (..), + IsTimestamped (..), + ) where + +import Data.Kind (Type) +import Deriving.Aeson +import Maestro.Types.Common (BlockHash, SlotNo) + +-- | Details of the most recent block processed by the indexer (aka chain tip); that is, the data returned is correct as of this block in time. +data LastUpdated = LastUpdated + { _lastUpdatedBlockHash :: !BlockHash + -- ^ Hash of the latest block. + , _lastUpdatedBlockSlot :: !SlotNo + -- ^ Slot number for the tip. + } + deriving stock (Eq, Ord, Show, Generic) + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_lastUpdated", CamelToSnake]] LastUpdated + +-- | Is the endpoint timestamped? +class IsTimestamped a where + -- | What is the type of the main data in question? + type TimestampedData a :: Type + -- | Get the main data from the value of the given type @a@. + getTimestampedData :: a -> TimestampedData a + -- | Get the `LastUpdated` field. + getTimestamp :: a -> LastUpdated diff --git a/src/Maestro/Types/V1/Datum.hs b/src/Maestro/Types/V1/Datum.hs index 913a497..70fcdcd 100644 --- a/src/Maestro/Types/V1/Datum.hs +++ b/src/Maestro/Types/V1/Datum.hs @@ -2,12 +2,14 @@ module Maestro.Types.V1.Datum ( Datum (..) + , TimestampedDatum (..) ) where import Data.Aeson (Value) import Data.Text (Text) import Deriving.Aeson -import Maestro.Types.V1.Common (LowerFirst) +import Maestro.Types.V1.Common (IsTimestamped (..), LastUpdated, + LowerFirst) -- | Details of datum when queried by it's hash. data Datum = Datum @@ -18,3 +20,18 @@ data Datum = Datum } deriving stock (Eq, Show, Generic) deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_datum", LowerFirst]] Datum + +-- | Timestamped `Datum` response. +data TimestampedDatum = TimestampedDatum + { _timestampedDatumData :: !Datum + -- ^ See `Datum`. + , _timestampedDatumLastUpdated :: !LastUpdated + -- ^ See `LastUpdated`. + } + deriving stock (Eq, Show, Generic) + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_timestampedDatum", CamelToSnake]] TimestampedDatum + +instance IsTimestamped TimestampedDatum where + type TimestampedData TimestampedDatum = Datum + getTimestampedData = _timestampedDatumData + getTimestamp = _timestampedDatumLastUpdated diff --git a/src/Maestro/Types/V1/General.hs b/src/Maestro/Types/V1/General.hs index 7bfb0dd..d0229b4 100644 --- a/src/Maestro/Types/V1/General.hs +++ b/src/Maestro/Types/V1/General.hs @@ -2,9 +2,9 @@ module Maestro.Types.V1.General ( -- * Types for @/system-start@ endpoint - SystemStart (..) + TimestampedSystemStart (..) -- * Types for @/era-history@ endpoint - , EraSummaries (..) + , TimestampedEraSummaries (..) , EraSummary (..) , EraParameters (..) , EraBound (..) @@ -16,11 +16,11 @@ module Maestro.Types.V1.General , MaestroRational (..) , textToMaestroRational , textFromMaestroRational + , TimestampedProtocolParameters (..) , ProtocolParameters (..) - , ProtocolParametersData (..) -- * Types for @/chain-tip@ endpoint + , TimestampedChainTip (..) , ChainTip (..) - , ChainTipData (..) ) where import Control.Monad (unless, when) @@ -36,7 +36,7 @@ import Data.Word (Word64) import Deriving.Aeson import Maestro.Types.V0.Common (BlockHash, EpochNo, EpochSize, LowerFirst, SlotNo) -import Maestro.Types.V1.Common (LastUpdated (..)) +import Maestro.Types.V1.Common (IsTimestamped (..), LastUpdated (..)) import Numeric.Natural (Natural) ------------------------------------------------------------------ @@ -44,28 +44,38 @@ import Numeric.Natural (Natural) ------------------------------------------------------------------ -- | Network start time since genesis. -data SystemStart = SystemStart - { _systemStartData :: !LocalTime +data TimestampedSystemStart = TimestampedSystemStart + { _timestampedSystemStartData :: !LocalTime -- ^ Network start time since genesis. - , _systemStartLastUpdated :: !LastUpdated + , _timestampedSystemStartLastUpdated :: !LastUpdated -- ^ See `LastUpdated`. } deriving stock (Eq, Ord, Show, Generic) - deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_systemStart", CamelToSnake]] SystemStart + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_timestampedSystemStart", CamelToSnake]] TimestampedSystemStart + +instance IsTimestamped TimestampedSystemStart where + type TimestampedData TimestampedSystemStart = LocalTime + getTimestampedData = _timestampedSystemStartData + getTimestamp = _timestampedSystemStartLastUpdated ------------------------------------------------------------------ -- Types for @/era-history@ endpoint ------------------------------------------------------------------ -- | Network era summaries. -data EraSummaries = EraSummaries - { _eraSummariesData :: ![EraSummary] +data TimestampedEraSummaries = TimestampedEraSummaries + { _timestampedEraSummariesData :: ![EraSummary] -- ^ Era summaries, see `EraSummary`. - , _eraSummariesLastUpdated :: !LastUpdated + , _timestampedEraSummariesLastUpdated :: !LastUpdated -- ^ See `LastUpdated`. } deriving stock (Eq, Show, Generic) - deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_eraSummaries", CamelToSnake]] EraSummaries + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_timestampedEraSummaries", CamelToSnake]] TimestampedEraSummaries + +instance IsTimestamped TimestampedEraSummaries where + type TimestampedData TimestampedEraSummaries = [EraSummary] + getTimestampedData = _timestampedEraSummariesData + getTimestamp = _timestampedEraSummariesLastUpdated -- | Network era summary. data EraSummary = EraSummary @@ -180,89 +190,98 @@ instance ToJSON MaestroRational where instance FromJSON MaestroRational where parseJSON = withText "MaestroRational" $ \ratTxt -> either fail pure $ textToMaestroRational ratTxt --- See `ProtocolParametersData`. -data ProtocolParameters = ProtocolParameters - { _protocolParametersData :: !ProtocolParametersData +-- | Timestamped `ProtocolParameters` response. +data TimestampedProtocolParameters = TimestampedProtocolParameters + { _timestampedProtocolParametersData :: !ProtocolParameters -- ^ See `ProtocolParametersData`. - , _protocolParametersLastUpdated :: !LastUpdated + , _timestampedProtocolParametersLastUpdated :: !LastUpdated -- ^ See `LastUpdated`. } deriving stock (Eq, Show, Generic) - deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_protocolParameters", CamelToSnake]] ProtocolParameters + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_timestampedProtocolParameters", CamelToSnake]] TimestampedProtocolParameters + +instance IsTimestamped TimestampedProtocolParameters where + type TimestampedData TimestampedProtocolParameters = ProtocolParameters + getTimestampedData = _timestampedProtocolParametersData + getTimestamp = _timestampedProtocolParametersLastUpdated -- | Protocol parameters for the latest epoch. -data ProtocolParametersData = ProtocolParametersData - { _protocolParametersDataProtocolVersion :: !ProtocolVersion +data ProtocolParameters = ProtocolParameters + { _protocolParametersProtocolVersion :: !ProtocolVersion -- ^ See `ProtocolVersion`. - , _protocolParametersDataMinFeeConstant :: !Natural + , _protocolParametersMinFeeConstant :: !Natural -- ^ The linear factor for the minimum fee calculation for given epoch /AKA/ @min_fee_b@ and @tx_fee_fixed@. - , _protocolParametersDataMinFeeCoefficient :: !Natural + , _protocolParametersMinFeeCoefficient :: !Natural -- ^ The constant factor for the minimum fee calculation /AKA/ @min_fee_a@ and @tx_fee_per_byte@. - , _protocolParametersDataMaxBlockBodySize :: !Natural + , _protocolParametersMaxBlockBodySize :: !Natural -- ^ Maximum block body size. - , _protocolParametersDataMaxBlockHeaderSize :: !Natural + , _protocolParametersMaxBlockHeaderSize :: !Natural -- ^ Maximum block header size. - , _protocolParametersDataMaxTxSize :: !Natural + , _protocolParametersMaxTxSize :: !Natural -- ^ Maximum transaction size. - , _protocolParametersDataStakeKeyDeposit :: !Natural + , _protocolParametersStakeKeyDeposit :: !Natural -- The deposit required to register a stake address. - , _protocolParametersDataPoolDeposit :: !Natural + , _protocolParametersPoolDeposit :: !Natural -- ^ The amount of a pool registration deposit in lovelaces /AKA/ @stake_pool_deposit@. - , _protocolParametersDataPoolRetirementEpochBound :: !EpochNo + , _protocolParametersPoolRetirementEpochBound :: !EpochNo -- ^ The maximum number of epochs into the future that stake pools are permitted to schedule a retirement /AKA/ @pool_retire_max_epoch@, @e_max@. - , _protocolParametersDataDesiredNumberOfPools :: !Natural + , _protocolParametersDesiredNumberOfPools :: !Natural -- The equilibrium target number of stake pools. This is the \"k\" incentives parameter from the design document, /AKA/ @n_opt@, @stake_pool_target@. - , _protocolParametersDataPoolInfluence :: !MaestroRational + , _protocolParametersPoolInfluence :: !MaestroRational -- The influence of the pledge in stake pool rewards. This is the \"a_0\" incentives parameter from the design document. - , _protocolParametersDataMonetaryExpansion :: !MaestroRational + , _protocolParametersMonetaryExpansion :: !MaestroRational -- ^ The monetary expansion rate. This determines the fraction of the reserves that are added to the fee pot each epoch. This is the \"rho\" incentives parameter from the design document. - , _protocolParametersDataTreasuryExpansion :: !MaestroRational + , _protocolParametersTreasuryExpansion :: !MaestroRational -- ^ The fraction of the fee pot each epoch that goes to the treasury. This is the \"tau\" incentives parameter from the design document, /AKA/ @treasury_cut@. - , _protocolParametersDataMinPoolCost :: !Natural + , _protocolParametersMinPoolCost :: !Natural -- ^ The minimum value that stake pools are permitted to declare for their cost parameter. - , _protocolParametersDataPrices :: !(MemoryStepsWith MaestroRational) + , _protocolParametersPrices :: !(MemoryStepsWith MaestroRational) -- ^ The price per unit memory & price per reduction step corresponding to abstract notions of the relative memory usage and script execution steps respectively. - , _protocolParametersDataMaxExecutionUnitsPerTransaction :: !(MemoryStepsWith Natural) + , _protocolParametersMaxExecutionUnitsPerTransaction :: !(MemoryStepsWith Natural) -- ^ The maximum number of execution memory & steps allowed to be used in a single transaction. - , _protocolParametersDataMaxExecutionUnitsPerBlock :: !(MemoryStepsWith Natural) + , _protocolParametersMaxExecutionUnitsPerBlock :: !(MemoryStepsWith Natural) -- ^ The maximum number of execution memory & steps allowed to be used in a single block. - , _protocolParametersDataMaxValueSize :: !Natural + , _protocolParametersMaxValueSize :: !Natural -- ^ Maximum size of the /value/ part of an output in a serialized transaction. - , _protocolParametersDataCollateralPercentage :: !Natural + , _protocolParametersCollateralPercentage :: !Natural -- ^ The percentage of the transactions fee which must be provided as collateral when including non-native scripts. - , _protocolParametersDataMaxCollateralInputs :: !Natural + , _protocolParametersMaxCollateralInputs :: !Natural -- ^ The maximum number of collateral inputs allowed in a transaction. - , _protocolParametersDataCoinsPerUtxoByte :: !Natural + , _protocolParametersCoinsPerUtxoByte :: !Natural -- ^ The cost per UTxO size. Cost per UTxO /word/ for Alozno. Cost per UTxO /byte/ for Babbage and later. - , _protocolParametersDataCostModels :: !CostModels + , _protocolParametersCostModels :: !CostModels -- ^ See `CostModels`. } deriving stock (Eq, Show, Generic) - deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_protocolParametersData", CamelToSnake]] ProtocolParametersData + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_protocolParameters", CamelToSnake]] ProtocolParameters ------------------------------------------------------------------ -- Types for @/chain-tip@ endpoint. ------------------------------------------------------------------ -- | Details about the most recently adopted block. -data ChainTipData = ChainTipData - { _chainTipDataBlockHash :: !BlockHash +data ChainTip = ChainTip + { _chainTipBlockHash :: !BlockHash -- ^ Hash of this most recent block. - , _chainTipDataSlot :: !SlotNo + , _chainTipSlot :: !SlotNo -- ^ Slot number for this most recent block. - , _chainTipDataHeight :: !Word64 + , _chainTipHeight :: !Word64 -- ^ Block number (height) of this most recent block. } deriving stock (Eq, Show, Generic) - deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_chainTipData", CamelToSnake]] ChainTipData - + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_chainTip", CamelToSnake]] ChainTip --- | See `ChainTipData`. -data ChainTip = ChainTip - { _chainTipData :: !ChainTipData - -- ^ See `ChainTipData`. - , _chainTipLastUpdated :: !LastUpdated +-- | Timestamped `ChainTip` response. +data TimestampedChainTip = TimestampedChainTip + { _timestampedChainTipData :: !ChainTip + -- ^ See `ChainTip`. + , _timestampedChainTipLastUpdated :: !LastUpdated -- ^ See `LastUpdated`. } deriving stock (Eq, Show, Generic) - deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_chainTip", CamelToSnake]] ChainTip + deriving (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_timestampedChainTip", CamelToSnake]] TimestampedChainTip + +instance IsTimestamped TimestampedChainTip where + type TimestampedData TimestampedChainTip = ChainTip + getTimestampedData = _timestampedChainTipData + getTimestamp = _timestampedChainTipLastUpdated diff --git a/src/Maestro/Types/V1/Pools.hs b/src/Maestro/Types/V1/Pools.hs index e6a94df..0e8547a 100644 --- a/src/Maestro/Types/V1/Pools.hs +++ b/src/Maestro/Types/V1/Pools.hs @@ -38,7 +38,10 @@ data PaginatedPoolListInfo = PaginatedPoolListInfo (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_paginatedPoolListInfo", CamelToSnake]] PaginatedPoolListInfo +instance IsTimestamped PaginatedPoolListInfo where + type TimestampedData PaginatedPoolListInfo = [PoolListInfo] + getTimestampedData = _paginatedPoolListInfoData + getTimestamp = _paginatedPoolListInfoLastUpdated + instance HasCursor PaginatedPoolListInfo where - type CursorData PaginatedPoolListInfo = [PoolListInfo] - getNextCursor pools = _paginatedPoolListInfoNextCursor pools - getCursorData pools = _paginatedPoolListInfoData pools + getNextCursor = _paginatedPoolListInfoNextCursor diff --git a/src/Maestro/Types/V1/Transactions.hs b/src/Maestro/Types/V1/Transactions.hs index b4a0af6..2957a36 100644 --- a/src/Maestro/Types/V1/Transactions.hs +++ b/src/Maestro/Types/V1/Transactions.hs @@ -82,7 +82,10 @@ data PaginatedUtxo = PaginatedUtxo (FromJSON, ToJSON) via CustomJSON '[FieldLabelModifier '[StripPrefix "_paginatedUtxo", CamelToSnake]] PaginatedUtxo +instance IsTimestamped PaginatedUtxo where + type TimestampedData PaginatedUtxo = [UtxoWithBytes] + getTimestampedData = _paginatedUtxoData + getTimestamp = _paginatedUtxoLastUpdated + instance HasCursor PaginatedUtxo where - type CursorData PaginatedUtxo = [UtxoWithBytes] - getNextCursor utxos = _paginatedUtxoNextCursor utxos - getCursorData utxos = _paginatedUtxoData utxos + getNextCursor = _paginatedUtxoNextCursor From 6535e0c1d426cb989a23c30fd5d747dbba2d8217 Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Mon, 10 Jul 2023 13:49:50 +0530 Subject: [PATCH 20/24] Feat 30: V1 Endpoints support - support for endpoints needed for Atlas - bug fix --- src/Maestro/Types/V1/Transactions.hs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Maestro/Types/V1/Transactions.hs b/src/Maestro/Types/V1/Transactions.hs index 2957a36..54c8b47 100644 --- a/src/Maestro/Types/V1/Transactions.hs +++ b/src/Maestro/Types/V1/Transactions.hs @@ -9,7 +9,6 @@ module Maestro.Types.V1.Transactions import Data.Aeson (ToJSON (..), Value (..)) import Data.Coerce (coerce) -import qualified Data.Text as T (pack) import Deriving.Aeson import Maestro.Types.Common import qualified Maestro.Types.V0 as V0 (Utxo (..)) @@ -21,7 +20,7 @@ data OutputReference = OutputReference !TxHash !TxIndex deriving stock (Show, Eq, Ord) instance ToHttpApiData OutputReference where - toQueryParam (OutputReference txHash txIndex) = coerce txHash <> "#" <> T.pack (show txIndex) + toQueryParam (OutputReference txHash txIndex) = toUrlPiece txHash <> "#" <> toUrlPiece txIndex instance ToJSON OutputReference where toJSON outputReference = String $ toQueryParam outputReference From 961ccffda9ae55ef071799af3faef012e71a657a Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Mon, 10 Jul 2023 19:15:16 +0530 Subject: [PATCH 21/24] Feat 30: V1 Endpoints support - README updated --- README.md | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 841e1ba..83a5b57 100644 --- a/README.md +++ b/README.md @@ -32,26 +32,35 @@ 1. Add `maestro-sdk` to the `build-depends` of your project. 2. Create a [Maestro API key](https://docs.gomaestro.org/docs/Getting-started/Sign-up-login). -3. Create environment for accessing the API: -```haskell -import Maestro.Client.Env +3. Code below explains sample usage. + ```haskell + module Main (main) where -myEnvPreprod <- mkMaestroEnv @'V0 "Your-API-Key" Preprod -myEnvMainnet <- mkMaestroEnv @'V0 "Your-API-Key" Mainnet -``` -4. Example: chain tip -```haskell -getChainTip myEnvPreprod -- Preprod -getChainTip myEnvMainnet -- Mainnet -``` + import Control.Exception (try) + import Maestro.Client.V1 -- @Maestro.Client.V1@ defines all the client utilities to query Maestro API endpoints. + import Maestro.Types.V1 -- @Maestro.Types.V1@ defines all the types used. -Other endpoints in the `General` category can be exmained in the [`Maestro.Client.General`](https://haddock.gomaestro.org/Maestro-Client-General.html) Haddock module. + main :: IO () + main = do + env <- mkMaestroEnv @'V1 "" Preprod -- This is how we create an environment against which we'll query endpoints. + chainTip :: ChainTip <- getTimestampedData <$> getChainTip env -- Maestro endpoint to get for chain-tip has data & timestamp against which data was calculated. All endpoints which are timestamped, has functions `getTimestampedData` to get for underlying data & `getTimestamp` to get the timestamp. + addressesUTxOs :: Either MaestroError [UtxoWithSlot] <- + try -- To catch for any errors, given in type `MaestroError`. + $ allPages -- Since this endpoint is paged, we have a helper utility `allPages` to accumulate data from all the pages. + $ flip + ( + utxosAtMultiAddresses env + (Just True) -- We would like to have datums resolved. This is for @resolve_datums@ query parameter. + (Just False) -- We would not like to include CBOR encodings of the transaction outputs in the response. + ) ["addr_test1...", "addr_test1...", "addr_test1..."] -- Mention your list of addresses to query for. + print addressesUTxOs + ``` # Documentation * [SDK Haddock](https://haddock.gomaestro.org/) * [Maestro public docs](https://docs.gomaestro.org/) -* [Maestro API reference](https://reference.gomaestro.org/) +* [Maestro API reference](https://docs.gomaestro.org/docs/category/rest-api-reference) # Contributing From 5b0e303309719789d7b7b523ed82c1f760e1cd6e Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Tue, 11 Jul 2023 13:11:02 +0530 Subject: [PATCH 22/24] Feat 30: V1 Endpoints support - cleaning run --- maestro-exe/Maestro/Run/Address.hs | 11 +++++++---- maestro-exe/Main.hs | 8 ++------ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/maestro-exe/Maestro/Run/Address.hs b/maestro-exe/Maestro/Run/Address.hs index 7322bc0..7ba2703 100644 --- a/maestro-exe/Maestro/Run/Address.hs +++ b/maestro-exe/Maestro/Run/Address.hs @@ -1,17 +1,20 @@ module Maestro.Run.Address where -import Control.Monad (when) +import Control.Monad (unless) import Data.List (sort) +import qualified Data.Text as T (pack) import Maestro.Client.Env import qualified Maestro.Client.V0 as V0 import qualified Maestro.Client.V1 as V1 import Maestro.Types.V1.Common (v1UtxoWithSlotToV0) -runAddressAPI :: MaestroEnv 'V0 -> MaestroEnv 'V1 -> IO () -runAddressAPI mEnvV0 mEnvV1 = do +runAddressAPI :: String -> IO () +runAddressAPI apiKey = do + mEnvV0 <- mkMaestroEnv @'V0 (T.pack apiKey) Preprod + mEnvV1 <- mkMaestroEnv @'V1 (T.pack apiKey) Preprod let addrs = undefined -- Mention list of addresses. utxos <- V0.allPages $ flip (V0.utxosAtMultiAddresses mEnvV0 Nothing Nothing) addrs let utxosSorted = sort utxos utxos' <- fmap (fmap v1UtxoWithSlotToV0) $ V1.allPages $ flip (V1.utxosAtMultiAddresses mEnvV1 Nothing Nothing) addrs let utxos'Sorted = sort utxos' - when (utxosSorted == utxos'Sorted) $ putStrLn "Yes" + unless (utxosSorted == utxos'Sorted) $ error "Not same" diff --git a/maestro-exe/Main.hs b/maestro-exe/Main.hs index f96d79a..64f50f8 100644 --- a/maestro-exe/Main.hs +++ b/maestro-exe/Main.hs @@ -2,7 +2,7 @@ module Main (main) where import qualified Data.Text as T import Maestro.Client.Env -import Maestro.Run.Address +-- import Maestro.Run.Address import Maestro.Run.Datum import Maestro.Run.Epochs import Maestro.Run.General @@ -16,7 +16,6 @@ main :: IO () main = do apiKey <- maestroKey - apiKeyMain <- maestroMainKey env <- mkMaestroEnv @'V0 (T.pack apiKey) Preprod runPoolsAPI env runTxApi env @@ -24,10 +23,7 @@ main = do runDatumAPI env runScriptsAPI env runGeneralAPI env - envV1 <- mkMaestroEnv @'V1 (T.pack apiKeyMain) Mainnet - envV0 <- mkMaestroEnv @'V0 (T.pack apiKeyMain) Mainnet - runAddressAPI envV0 envV1 + -- runAddressAPI apiKey where maestroKey = getEnv "MAESTRO_API_KEY" - maestroMainKey = getEnv "MAESTRO_MAIN_KEY" From 8db3672fb3e9744e62fd2996ee9dba2820b8b5db Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Tue, 11 Jul 2023 15:12:50 +0530 Subject: [PATCH 23/24] Feat 30: V1 Endpoints support - haddock improvement --- src/Maestro/Client/V1/Addresses.hs | 2 +- src/Maestro/Client/V1/Pools.hs | 2 +- src/Maestro/Client/V1/TxManager.hs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Maestro/Client/V1/Addresses.hs b/src/Maestro/Client/V1/Addresses.hs index 3004fe4..346618f 100644 --- a/src/Maestro/Client/V1/Addresses.hs +++ b/src/Maestro/Client/V1/Addresses.hs @@ -38,7 +38,7 @@ getRefsAtAddress :: MaestroEnv 'V1 -> -- | The Address in Bech32 format. Bech32StringOf Address -> - -- | The pagination attributes + -- | The pagination attributes. Cursor -> IO PaginatedOutputReferenceObject getRefsAtAddress = _addressUtxoRefs . addressClient diff --git a/src/Maestro/Client/V1/Pools.hs b/src/Maestro/Client/V1/Pools.hs index cad7af3..f87fd20 100644 --- a/src/Maestro/Client/V1/Pools.hs +++ b/src/Maestro/Client/V1/Pools.hs @@ -16,6 +16,6 @@ import Servant.Client poolsClient :: MaestroEnv 'V1 -> PoolsAPI (AsClientT IO) poolsClient = fromServant . _pools . apiV1Client --- | Returns a list of currently registered stake pools +-- | Returns a list of currently registered stake pools. listPools :: MaestroEnv 'V1 -> Cursor -> IO PaginatedPoolListInfo listPools = _listPools . poolsClient diff --git a/src/Maestro/Client/V1/TxManager.hs b/src/Maestro/Client/V1/TxManager.hs index 49c69a6..ddab311 100644 --- a/src/Maestro/Client/V1/TxManager.hs +++ b/src/Maestro/Client/V1/TxManager.hs @@ -17,9 +17,9 @@ txClient = fromServant . _txManager . apiV1Client -- | Submit a signed and serialized transaction to the network. A transaction submited with this endpoint will be monitored by Maestro. submitAndMonitorTx :: - -- | The Maestro Environment + -- | The Maestro Environment. MaestroEnv 'V1 -> - -- | CBOR encoded Transaction + -- | CBOR encoded Transaction. BS.ByteString -> IO Text submitAndMonitorTx = _monitoredTxSubmit . txClient From 8180f26a011dcb465c13cb29d19abf055f38c19c Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Fri, 14 Jul 2023 21:16:51 +0530 Subject: [PATCH 24/24] Feat 30: V1 Endpoints support - turbo submit endpoint + version set to 1.0.0 --- maestro-sdk.cabal | 2 +- src/Maestro/API/V1/TxManager.hs | 6 +++++- src/Maestro/Client/V1/TxManager.hs | 10 ++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/maestro-sdk.cabal b/maestro-sdk.cabal index 4189f4d..bfac535 100644 --- a/maestro-sdk.cabal +++ b/maestro-sdk.cabal @@ -1,6 +1,6 @@ cabal-version: 3.0 name: maestro-sdk -version: 0.1.0.0 +version: 1.0.0 synopsis: Maestro Blockchain Indexer SDK description: Maestro provides blockchain indexers, APIs and event management systems for the Cardano blockchain. license: Apache-2.0 diff --git a/src/Maestro/API/V1/TxManager.hs b/src/Maestro/API/V1/TxManager.hs index d388331..6da8cd7 100644 --- a/src/Maestro/API/V1/TxManager.hs +++ b/src/Maestro/API/V1/TxManager.hs @@ -6,10 +6,14 @@ import Maestro.Types.V1 import Servant.API import Servant.API.Generic -newtype TxManagerAPI route = TxManagerAPI +data TxManagerAPI route = TxManagerAPI { _monitoredTxSubmit :: route :- ReqBody' '[Required] '[CBORStream] BS.ByteString :> PostAccepted '[JSON] T.Text + , _monitoredTurboTxSubmit :: + route + :- ReqBody' '[Required] '[CBORStream] BS.ByteString + :> PostAccepted '[JSON] T.Text } deriving (Generic) diff --git a/src/Maestro/Client/V1/TxManager.hs b/src/Maestro/Client/V1/TxManager.hs index ddab311..fe82b78 100644 --- a/src/Maestro/Client/V1/TxManager.hs +++ b/src/Maestro/Client/V1/TxManager.hs @@ -1,5 +1,6 @@ module Maestro.Client.V1.TxManager ( submitAndMonitorTx + , turboSubmitAndMonitorTx ) where @@ -23,3 +24,12 @@ submitAndMonitorTx :: BS.ByteString -> IO Text submitAndMonitorTx = _monitoredTxSubmit . txClient + +-- | Submit a signed and serialized transaction to the network. A transaction submited with this endpoint will be [turbo submitted & monitored by Maestro](https://docs.gomaestro.org/docs/API%20reference/Transaction%20Manager/tx-manager-turbo-submit). +turboSubmitAndMonitorTx :: + -- | The Maestro Environment. + MaestroEnv 'V1 -> + -- | CBOR encoded Transaction. + BS.ByteString -> + IO Text +turboSubmitAndMonitorTx = _monitoredTurboTxSubmit . txClient