-- | Node IPC protocols
--
-- This module provides the client side of the node-to-client interprocess
-- communication (IPC) for interacting with a local Cardano node. It supports
-- querying the node for information, submitting transactions, monitoring
-- the local mempool, and retrieving historical chain data using the
-- @ChainSync@ protocol.
module Cardano.Api.Network.IPC
  ( -- * Examples

    -- | This section provides two examples:
    --
    --    1. Querying the node to obtain basic information
    --    2. Submitting a transaction to the node.
    --
    -- For details on how to create a transaction, see the
    -- "Cardano.Api.Tx.Internal.Body" documentation.
    --
    -- The following qualified imports from @cardano-api@ are
    -- used in the examples below:
    --
    -- @
    -- import qualified Cardano.Api as Api
    -- import qualified Cardano.Api.Consensus as Consensus
    -- import qualified Cardano.Api.Network as Network
    -- @
    --
    -- The following explicit import from @base@ is also required:
    --
    -- @
    -- import Control.Monad.Except (runExceptT)
    -- @
    --
    -- The examples assume the use of the @IO@ monad and unqualified
    -- access to the @Prelude@ module.

    -- ** Constructing connection information

    -- | Regardless of whether the goal is to query the node or submit transactions,
    -- the first step is to gather the connection information.
    --
    -- The following information is required:
    --
    --    * __The number of slots per epoch__. This value depends on the network the
    --      node is connected to. It can be obtained by inspecting the @epochLength@
    --      key in the @shelley-genesis.json@ file used by the node. On the preview
    --      network, the value is, at the time of writing, @86_400@, but it can
    --      change. This value and other genesis parameters can also be obtained
    --      using the 'QueryGenesisParameters' query.
    --    * __Network identifier__. When connecting to a testnet, the network identifier
    --      is also required. It can be obtained by looking for the @networkId@
    --      obtained by looking up the @networkMagic@ key in the @shelley-genesis.json@
    --      file that the node uses to connect to the network. For the preview
    --      network, the current identifier is @2@.
    --    * __Socket path__. The path to the node's socket file. It can be set using
    --      the @--socket-path@ parameter when starting the node. By default, it is
    --      typically located in the @db@ subfolder of the node's working directory.
    --
    --  Then, combine all the required information into a 'LocalNodeConnectInfo' value.
    --
    --  For example, assume the node is connected to the preview network and the socket
    --  file is located at @\/home\/user\/cardano-node\/db\/node.socket@. The
    --  'LocalNodeConnectInfo' value can then be constructed as follows:
    --
    -- @
    -- let connectionInfo =
    --       Api.LocalNodeConnectInfo
    --          { Api.localConsensusModeParams = Api.CardanoModeParams (Api.EpochSlots 86_400)
    --          , Api.localNodeNetworkId = Api.Testnet (Api.NetworkMagic 2)
    --          , Api.localNodeSocketPath = Api.File "\/home\/user\/cardano-node\/db\/node.socket"
    --          }
    -- @

    -- ** Querying the node for the UTXO set

    -- | To obtain the set of unspent transaction outputs (UTXO set) from the network,
    -- the current era must first be determined.

    -- *** Obtaining the current era

    -- | Many queries require knowing the current era. This can be hardcoded using one of
    -- the 'ShelleyBasedEra' constructors, but it is also possible to retreive it from
    -- the node:
    --
    -- @
    -- eEra <- runExceptT $ Api.queryNodeLocalState connectionInfo Network.VolatileTip Api.QueryCurrentEra
    -- @
    --
    -- 'VolatileTip' requests information from the most recent block the node is aware of.
    -- It is important to note that this information is not guaranteed to remain valid, as
    -- it may be rolled back.
    --
    -- Alternatively, 'ImmutableTip' can be used to obtain information from the most recent
    -- block considered as final by the consensus algorithm. While this data is stable and will
    -- not be rolled back, it is less recent – on mainnet, it is typically about 36 hours
    -- behind the current time.
    --
    -- 'QueryCurrentEra' is the constructor of the query that retrieves the node's current
    -- era.
    --
    -- The query returns an 'ExceptT' monad, which can be run using the 'runExceptT'
    -- function. This yields an @eEra@ value of type @Either AcquiringFailure AnyCardanoEra@.
    --
    -- Below is an example of how to unwrap this value into a 'ShelleyBasedEra' based era, assuming the node
    -- is not running Byron:
    --
    -- @
    -- Api.AnyShelleyBasedEra sbe :: Api.AnyShelleyBasedEra <- case eEra of
    --   Right (Api.AnyCardanoEra era) ->
    --     Api.caseByronOrShelleyBasedEra
    --       (error "Error, we are in Byron era")
    --       (return . Api.AnyShelleyBasedEra)
    --       era
    --   Left Shelley.AFPointTooOld -> error "Error, point queried in the chain is too old!"
    --   Left Shelley.AFPointNotOnChain -> error "Error, point queried is not on chain!"
    -- @
    --
    -- 'AFPointTooOld' and 'AFPointNotOnChain' errors should not occur when querying with
    -- either 'VolatileTip' or 'ImmutableTip'.

    -- *** Obtaining the UTXO set

    -- | After determining the current era, the node can be queried for the UTXO set using
    -- the 'QueryUTxO' query as follows:
    --
    -- @
    -- eUtxo <-
    --   runExceptT $
    --     Api.queryNodeLocalState
    --       connectionInfo
    --       Network.VolatileTip
    --       (Api.QueryInEra (Api.QueryInShelleyBasedEra sbe (Api.QueryUTxO Api.QueryUTxOWhole)))
    -- @
    --
    -- This returns, a nested type of @Either AcquiringFailure (Either EraMismatch (UTXO era))@.
    -- You can unwrap it as follows:
    --
    -- @
    -- utxo <- case eUtxo of
    --   Right (Right (Api.UTxO utxo)) -> do
    --     return utxo
    --   Right (Left (Consensus.EraMismatch{Consensus.ledgerEraName, Consensus.otherEraName})) ->
    --     error
    --       ( "Error, we assumed era was "
    --           ++ show otherEraName
    --           ++ " but it was "
    --           ++ show ledgerEraName
    --       )
    --   Left Shelley.AFPointTooOld -> error "Error, point queried in the chain is too old!"
    --   Left Shelley.AFPointNotOnChain -> error "Error, point queried is not on chain!"
    -- @
    --
    -- Alternatively, to avoid nested result types, you can use convenience
    -- functions and types from "Cardano.Api.Query.Internal.Convenience".
    -- It is also posible to combine several queries into a single connection by using
    -- the monadic interface that can be found in the "Cardano.Api.Network.IPC.Internal.Monad"
    -- documentation.
    --
    -- The obtained @utxo@ variable is a standard @Map@ of type @Map TxIn (TxOut CtxUTxO era)@.

    -- ** Submitting a transaction

    -- | Assume there is a signed transaction in the latest era that you would like to submit
    -- to the node. Assume it is stored in the variable @signedTx@ of type @Tx era@.
    --
    -- For details on how to create such a transaction, see the "Cardano.Api.Tx.Internal.Body"
    -- documentation.
    --
    -- To submit the transaction to the node, use the 'submitTxToNodeLocal' function as follows:
    --
    -- @
    -- result <- Api.submitTxToNodeLocal connectionInfo (Api.TxInMode sbe signedTx)
    -- @
    --
    -- The result is a 'SubmitResult' value, which can be inspected as follows:
    --
    -- @
    -- case result of
    --   Api.SubmitSuccess -> putStrLn "Transaction submitted successfully!"
    --   Api.SubmitFail reason -> error $ "Error submitting transaction: " ++ show reason
    -- @
    --
    -- If the command succeeds, the transaction gets into the node's mempool, ready
    -- to be included in a block.

    -- * Node interaction

    -- | Operations that involve talking to a local Cardano node.
    connectToLocalNode
  , connectToLocalNodeWithVersion
  , LocalNodeConnectInfo (..)
  , LocalNodeClientParams (..)
  , mkLocalNodeClientParams
  , LocalNodeClientProtocols (..)
  , LocalChainSyncClient (..)
  , LocalNodeClientProtocolsInMode

    -- *** Chain sync protocol
  , ChainSyncClient (..)
  , ChainSyncClientPipelined (..)
  , BlockInMode (..)

    -- *** Local tx submission
  , LocalTxSubmissionClient (..)
  , TxInMode (..)
  , TxValidationErrorInCardanoMode
  , TxValidationError
  , submitTxToNodeLocal
  , SubmitResult (..)

    -- *** Local state query
  , LocalStateQueryClient (..)
  , AcquiringFailure (..)
  , QueryInMode (..)
  , QueryInEra (..)
  , QueryInShelleyBasedEra (..)
  , queryNodeLocalState

    -- **** Query monad
  , LocalStateQueryExpr
  , executeLocalStateQueryExpr
  , queryExpr

    -- *** Local tx monitoring
  , LocalTxMonitorClient (..)
  , LocalTxMonitoringQuery (..)
  , LocalTxMonitoringResult (..)
  , MempoolSizeAndCapacity (..)
  , queryTxMonitoringLocal
  , EraHistory (..)
  , getProgress

    -- *** Common queries
  , getLocalChainTip

    -- *** Query versioning
  , isQuerySupportedInNtcVersion
  , NodeToClientVersion (..)

    -- *** Error types
  , UnsupportedNtcVersionError (..)

    -- *** Helpers
  , toAcquiringFailure
  )
where

import Cardano.Api.Network.IPC.Internal
import Cardano.Api.Network.IPC.Internal.Monad
import Cardano.Api.Network.IPC.Internal.Version