{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilyDependencies #-}

-- | Cardano eras, sometimes we have to distinguish them.
module Cardano.Api.Eras.Core
  ( -- * Eras
    ByronEra
  , ShelleyEra
  , AllegraEra
  , MaryEra
  , AlonzoEra
  , BabbageEra
  , ConwayEra

    -- * CardanoEra
  , CardanoEra (..)
  , IsCardanoEra (..)
  , AnyCardanoEra (..)
  , anyCardanoEra
  , InAnyCardanoEra (..)
  , inAnyCardanoEra
  , CardanoLedgerEra
  , ToCardanoEra (..)

    -- * IsEon
  , Eon (..)
  , EraInEon (..)
  , inEonForEraMaybe
  , forEraInEon
  , forEraInEonMaybe
  , forEraMaybeEon
  , maybeEon
  , monoidForEraInEon
  , monoidForEraInEonA

    -- * Data family instances
  , AsType (AsByronEra, AsShelleyEra, AsAllegraEra, AsMaryEra, AsAlonzoEra, AsBabbageEra, AsConwayEra)
  , CardanoEraConstraints
  , cardanoEraConstraints
  )
where

import           Cardano.Api.HasTypeProxy
import           Cardano.Api.Pretty

import qualified Cardano.Ledger.Api as L

import           Data.Aeson (FromJSON (..), ToJSON, toJSON, withText)
import           Data.Kind
import           Data.Maybe (isJust)
import           Data.String (IsString)
import qualified Data.Text as Text
import           Data.Type.Equality (TestEquality (..), (:~:) (Refl))
import           Data.Typeable (Typeable, showsTypeRep, typeOf)

-- ----------------------------------------------------------------------------
-- Eras

-- | A type used as a tag to distinguish the Byron era.
data ByronEra

-- | A type used as a tag to distinguish the Shelley era.
data ShelleyEra

-- | A type used as a tag to distinguish the Allegra era.
data AllegraEra

-- | A type used as a tag to distinguish the Mary era.
data MaryEra

-- | A type used as a tag to distinguish the Alonzo era.
data AlonzoEra

-- | A type used as a tag to distinguish the Babbage era.
data BabbageEra

-- | A type used as a tag to distinguish the Conway era.
data ConwayEra

instance HasTypeProxy ByronEra where
  data AsType ByronEra = AsByronEra
  proxyToAsType :: Proxy ByronEra -> AsType ByronEra
proxyToAsType Proxy ByronEra
_ = AsType ByronEra
AsByronEra

instance HasTypeProxy ShelleyEra where
  data AsType ShelleyEra = AsShelleyEra
  proxyToAsType :: Proxy ShelleyEra -> AsType ShelleyEra
proxyToAsType Proxy ShelleyEra
_ = AsType ShelleyEra
AsShelleyEra

instance HasTypeProxy AllegraEra where
  data AsType AllegraEra = AsAllegraEra
  proxyToAsType :: Proxy AllegraEra -> AsType AllegraEra
proxyToAsType Proxy AllegraEra
_ = AsType AllegraEra
AsAllegraEra

instance HasTypeProxy MaryEra where
  data AsType MaryEra = AsMaryEra
  proxyToAsType :: Proxy MaryEra -> AsType MaryEra
proxyToAsType Proxy MaryEra
_ = AsType MaryEra
AsMaryEra

instance HasTypeProxy AlonzoEra where
  data AsType AlonzoEra = AsAlonzoEra
  proxyToAsType :: Proxy AlonzoEra -> AsType AlonzoEra
proxyToAsType Proxy AlonzoEra
_ = AsType AlonzoEra
AsAlonzoEra

instance HasTypeProxy BabbageEra where
  data AsType BabbageEra = AsBabbageEra
  proxyToAsType :: Proxy BabbageEra -> AsType BabbageEra
proxyToAsType Proxy BabbageEra
_ = AsType BabbageEra
AsBabbageEra

instance HasTypeProxy ConwayEra where
  data AsType ConwayEra = AsConwayEra
  proxyToAsType :: Proxy ConwayEra -> AsType ConwayEra
proxyToAsType Proxy ConwayEra
_ = AsType ConwayEra
AsConwayEra

-- ----------------------------------------------------------------------------
-- Eon

-- | An Eon is a span of multiple eras.  Eons are used to scope functionality to
-- particular eras such that it isn't possible construct code that uses functionality
-- that is outside of given eras.
class Eon (eon :: Type -> Type) where
  -- | Determine the value to use in an eon (a span of multiple eras).
  -- Note that the negative case is the first argument, and the positive case is the second as per
  -- the 'either' function convention.
  inEonForEra
    :: ()
    => a
    -- ^ Value to use if the eon does not include the era
    -> (eon era -> a)
    -- ^ Function to get the value to use if the eon includes the era
    -> CardanoEra era
    -- ^ Era to check
    -> a
    -- ^ The value to use

inEonForEraMaybe
  :: ()
  => Eon eon
  => (eon era -> a)
  -- ^ Function to get the value to use if the eon includes the era
  -> CardanoEra era
  -- ^ Era to check
  -> Maybe a
  -- ^ The value to use
inEonForEraMaybe :: forall (eon :: * -> *) era a.
Eon eon =>
(eon era -> a) -> CardanoEra era -> Maybe a
inEonForEraMaybe eon era -> a
yes =
  Maybe a -> (eon era -> Maybe a) -> CardanoEra era -> Maybe a
forall a era. a -> (eon era -> a) -> CardanoEra era -> a
forall (eon :: * -> *) a era.
Eon eon =>
a -> (eon era -> a) -> CardanoEra era -> a
inEonForEra Maybe a
forall a. Maybe a
Nothing (a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> (eon era -> a) -> eon era -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. eon era -> a
yes)

forEraInEon
  :: ()
  => Eon eon
  => CardanoEra era
  -- ^ Era to check
  -> a
  -- ^ Value to use if the eon does not include the era
  -> (eon era -> a)
  -- ^ Function to get the value to use if the eon includes the era
  -> a
  -- ^ The value to use
forEraInEon :: forall (eon :: * -> *) era a.
Eon eon =>
CardanoEra era -> a -> (eon era -> a) -> a
forEraInEon CardanoEra era
era a
no eon era -> a
yes =
  a -> (eon era -> a) -> CardanoEra era -> a
forall a era. a -> (eon era -> a) -> CardanoEra era -> a
forall (eon :: * -> *) a era.
Eon eon =>
a -> (eon era -> a) -> CardanoEra era -> a
inEonForEra a
no eon era -> a
yes CardanoEra era
era

forEraInEonMaybe
  :: ()
  => Eon eon
  => CardanoEra era
  -- ^ Era to check
  -> (eon era -> a)
  -- ^ Function to get the value to use if the eon includes the era
  -> Maybe a
  -- ^ The value to use
forEraInEonMaybe :: forall (eon :: * -> *) era a.
Eon eon =>
CardanoEra era -> (eon era -> a) -> Maybe a
forEraInEonMaybe CardanoEra era
era eon era -> a
yes =
  CardanoEra era -> Maybe a -> (eon era -> Maybe a) -> Maybe a
forall (eon :: * -> *) era a.
Eon eon =>
CardanoEra era -> a -> (eon era -> a) -> a
forEraInEon CardanoEra era
era Maybe a
forall a. Maybe a
Nothing (a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> (eon era -> a) -> eon era -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. eon era -> a
yes)

forEraMaybeEon
  :: ()
  => Eon eon
  => CardanoEra era
  -- ^ Era to check
  -> Maybe (eon era)
  -- ^ The eon if supported in the era
forEraMaybeEon :: forall (eon :: * -> *) era.
Eon eon =>
CardanoEra era -> Maybe (eon era)
forEraMaybeEon =
  Maybe (eon era)
-> (eon era -> Maybe (eon era))
-> CardanoEra era
-> Maybe (eon era)
forall a era. a -> (eon era -> a) -> CardanoEra era -> a
forall (eon :: * -> *) a era.
Eon eon =>
a -> (eon era -> a) -> CardanoEra era -> a
inEonForEra Maybe (eon era)
forall a. Maybe a
Nothing eon era -> Maybe (eon era)
forall a. a -> Maybe a
Just

maybeEon
  :: ()
  => Eon eon
  => IsCardanoEra era
  => Maybe (eon era)
  -- ^ The eon if supported in the era
maybeEon :: forall (eon :: * -> *) era.
(Eon eon, IsCardanoEra era) =>
Maybe (eon era)
maybeEon =
  Maybe (eon era)
-> (eon era -> Maybe (eon era))
-> CardanoEra era
-> Maybe (eon era)
forall a era. a -> (eon era -> a) -> CardanoEra era -> a
forall (eon :: * -> *) a era.
Eon eon =>
a -> (eon era -> a) -> CardanoEra era -> a
inEonForEra Maybe (eon era)
forall a. Maybe a
Nothing eon era -> Maybe (eon era)
forall a. a -> Maybe a
Just CardanoEra era
forall era. IsCardanoEra era => CardanoEra era
cardanoEra

monoidForEraInEon
  :: ()
  => Eon eon
  => Monoid a
  => CardanoEra era
  -> (eon era -> a)
  -> a
monoidForEraInEon :: forall (eon :: * -> *) a era.
(Eon eon, Monoid a) =>
CardanoEra era -> (eon era -> a) -> a
monoidForEraInEon CardanoEra era
sbe = CardanoEra era -> a -> (eon era -> a) -> a
forall (eon :: * -> *) era a.
Eon eon =>
CardanoEra era -> a -> (eon era -> a) -> a
forEraInEon CardanoEra era
sbe a
forall a. Monoid a => a
mempty

monoidForEraInEonA
  :: ()
  => Eon eon
  => Applicative f
  => Monoid a
  => CardanoEra era
  -> (eon era -> f a)
  -> f a
monoidForEraInEonA :: forall (eon :: * -> *) (f :: * -> *) a era.
(Eon eon, Applicative f, Monoid a) =>
CardanoEra era -> (eon era -> f a) -> f a
monoidForEraInEonA CardanoEra era
sbe = CardanoEra era -> f a -> (eon era -> f a) -> f a
forall (eon :: * -> *) era a.
Eon eon =>
CardanoEra era -> a -> (eon era -> a) -> a
forEraInEon CardanoEra era
sbe (a -> f a
forall a. a -> f a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
forall a. Monoid a => a
mempty)

-- ----------------------------------------------------------------------------
-- Era and eon existential types

data EraInEon eon where
  EraInEon
    :: ( Typeable era
       , Typeable (eon era)
       , Eon eon
       )
    => eon era
    -> EraInEon eon

-- | Assumes that eons are singletons
instance Show (EraInEon eon) where
  showsPrec :: Int -> EraInEon eon -> ShowS
showsPrec Int
_ (EraInEon eon era
eonEra) = TypeRep -> ShowS
showsTypeRep (eon era -> TypeRep
forall a. Typeable a => a -> TypeRep
typeOf eon era
eonEra)

-- | Assumes that eons are singletons
instance TestEquality eon => Eq (EraInEon eon) where
  EraInEon eon era
era1 == :: EraInEon eon -> EraInEon eon -> Bool
== EraInEon eon era
era2 =
    Maybe (era :~: era) -> Bool
forall a. Maybe a -> Bool
isJust (Maybe (era :~: era) -> Bool) -> Maybe (era :~: era) -> Bool
forall a b. (a -> b) -> a -> b
$ eon era -> eon era -> Maybe (era :~: era)
forall a b. eon a -> eon b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
testEquality eon era
era1 eon era
era2

-- ----------------------------------------------------------------------------
-- ToCardanoEra

class ToCardanoEra (eon :: Type -> Type) where
  toCardanoEra
    :: ()
    => eon era
    -> CardanoEra era

-- ----------------------------------------------------------------------------
-- Value level representation for Cardano eras
--

-- | This GADT provides a value-level representation of all the Cardano eras.
-- This enables pattern matching on the era to allow them to be treated in a
-- non-uniform way.
--
-- This can be used in combination with the 'IsCardanoEra' class to get access
-- to this value.
--
-- In combination this can often enable code that handles all eras, and does
-- so uniformly where possible, and non-uniformly where necessary.
data CardanoEra era where
  ByronEra :: CardanoEra ByronEra
  ShelleyEra :: CardanoEra ShelleyEra
  AllegraEra :: CardanoEra AllegraEra
  MaryEra :: CardanoEra MaryEra
  AlonzoEra :: CardanoEra AlonzoEra
  BabbageEra :: CardanoEra BabbageEra
  ConwayEra :: CardanoEra ConwayEra

-- when you add era here, change `instance Bounded AnyCardanoEra`

deriving instance Eq (CardanoEra era)

deriving instance Ord (CardanoEra era)

deriving instance Show (CardanoEra era)

instance Pretty (CardanoEra era) where
  pretty :: forall ann. CardanoEra era -> Doc ann
pretty = CardanoEra era -> Doc ann
forall a era. IsString a => CardanoEra era -> a
cardanoEraToStringLike

instance ToJSON (CardanoEra era) where
  toJSON :: CardanoEra era -> Value
toJSON = CardanoEra era -> Value
forall a era. IsString a => CardanoEra era -> a
cardanoEraToStringLike

instance TestEquality CardanoEra where
  testEquality :: forall a b. CardanoEra a -> CardanoEra b -> Maybe (a :~: b)
testEquality CardanoEra a
ByronEra CardanoEra b
ByronEra = (a :~: b) -> Maybe (a :~: b)
forall a. a -> Maybe a
Just a :~: a
a :~: b
forall {k} (a :: k). a :~: a
Refl
  testEquality CardanoEra a
ShelleyEra CardanoEra b
ShelleyEra = (a :~: b) -> Maybe (a :~: b)
forall a. a -> Maybe a
Just a :~: a
a :~: b
forall {k} (a :: k). a :~: a
Refl
  testEquality CardanoEra a
AllegraEra CardanoEra b
AllegraEra = (a :~: b) -> Maybe (a :~: b)
forall a. a -> Maybe a
Just a :~: a
a :~: b
forall {k} (a :: k). a :~: a
Refl
  testEquality CardanoEra a
MaryEra CardanoEra b
MaryEra = (a :~: b) -> Maybe (a :~: b)
forall a. a -> Maybe a
Just a :~: a
a :~: b
forall {k} (a :: k). a :~: a
Refl
  testEquality CardanoEra a
AlonzoEra CardanoEra b
AlonzoEra = (a :~: b) -> Maybe (a :~: b)
forall a. a -> Maybe a
Just a :~: a
a :~: b
forall {k} (a :: k). a :~: a
Refl
  testEquality CardanoEra a
BabbageEra CardanoEra b
BabbageEra = (a :~: b) -> Maybe (a :~: b)
forall a. a -> Maybe a
Just a :~: a
a :~: b
forall {k} (a :: k). a :~: a
Refl
  testEquality CardanoEra a
ConwayEra CardanoEra b
ConwayEra = (a :~: b) -> Maybe (a :~: b)
forall a. a -> Maybe a
Just a :~: a
a :~: b
forall {k} (a :: k). a :~: a
Refl
  testEquality CardanoEra a
_ CardanoEra b
_ = Maybe (a :~: b)
forall a. Maybe a
Nothing

instance Eon CardanoEra where
  inEonForEra :: forall a era. a -> (CardanoEra era -> a) -> CardanoEra era -> a
inEonForEra a
_ CardanoEra era -> a
yes = CardanoEra era -> a
yes

instance ToCardanoEra CardanoEra where
  toCardanoEra :: forall era. CardanoEra era -> CardanoEra era
toCardanoEra = CardanoEra era -> CardanoEra era
forall a. a -> a
id

-- | The class of Cardano eras. This allows uniform handling of all Cardano
-- eras, but also non-uniform by making case distinctions on the 'CardanoEra'
-- constructors.
class HasTypeProxy era => IsCardanoEra era where
  cardanoEra :: CardanoEra era

instance IsCardanoEra ByronEra where
  cardanoEra :: CardanoEra ByronEra
cardanoEra = CardanoEra ByronEra
ByronEra

instance IsCardanoEra ShelleyEra where
  cardanoEra :: CardanoEra ShelleyEra
cardanoEra = CardanoEra ShelleyEra
ShelleyEra

instance IsCardanoEra AllegraEra where
  cardanoEra :: CardanoEra AllegraEra
cardanoEra = CardanoEra AllegraEra
AllegraEra

instance IsCardanoEra MaryEra where
  cardanoEra :: CardanoEra MaryEra
cardanoEra = CardanoEra MaryEra
MaryEra

instance IsCardanoEra AlonzoEra where
  cardanoEra :: CardanoEra AlonzoEra
cardanoEra = CardanoEra AlonzoEra
AlonzoEra

instance IsCardanoEra BabbageEra where
  cardanoEra :: CardanoEra BabbageEra
cardanoEra = CardanoEra BabbageEra
BabbageEra

instance IsCardanoEra ConwayEra where
  cardanoEra :: CardanoEra ConwayEra
cardanoEra = CardanoEra ConwayEra
ConwayEra

type CardanoEraConstraints era =
  ( Typeable era
  , IsCardanoEra era
  )

cardanoEraConstraints
  :: ()
  => CardanoEra era
  -> (CardanoEraConstraints era => a)
  -> a
cardanoEraConstraints :: forall era a.
CardanoEra era -> (CardanoEraConstraints era => a) -> a
cardanoEraConstraints = \case
  CardanoEra era
ByronEra -> a -> a
(CardanoEraConstraints era => a) -> a
forall a. a -> a
id
  CardanoEra era
ShelleyEra -> a -> a
(CardanoEraConstraints era => a) -> a
forall a. a -> a
id
  CardanoEra era
AllegraEra -> a -> a
(CardanoEraConstraints era => a) -> a
forall a. a -> a
id
  CardanoEra era
MaryEra -> a -> a
(CardanoEraConstraints era => a) -> a
forall a. a -> a
id
  CardanoEra era
AlonzoEra -> a -> a
(CardanoEraConstraints era => a) -> a
forall a. a -> a
id
  CardanoEra era
BabbageEra -> a -> a
(CardanoEraConstraints era => a) -> a
forall a. a -> a
id
  CardanoEra era
ConwayEra -> a -> a
(CardanoEraConstraints era => a) -> a
forall a. a -> a
id

data AnyCardanoEra where
  AnyCardanoEra
    :: Typeable era
    => CardanoEra era
    -> AnyCardanoEra

deriving instance Show AnyCardanoEra

instance Pretty AnyCardanoEra where
  pretty :: forall ann. AnyCardanoEra -> Doc ann
pretty (AnyCardanoEra CardanoEra era
e) = CardanoEra era -> Doc ann
forall a ann. Pretty a => a -> Doc ann
forall ann. CardanoEra era -> Doc ann
pretty CardanoEra era
e

-- | Assumes that 'CardanoEra era' are singletons
instance Eq AnyCardanoEra where
  AnyCardanoEra CardanoEra era
era == :: AnyCardanoEra -> AnyCardanoEra -> Bool
== AnyCardanoEra CardanoEra era
era' =
    Maybe (era :~: era) -> Bool
forall a. Maybe a -> Bool
isJust (Maybe (era :~: era) -> Bool) -> Maybe (era :~: era) -> Bool
forall a b. (a -> b) -> a -> b
$ CardanoEra era -> CardanoEra era -> Maybe (era :~: era)
forall a b. CardanoEra a -> CardanoEra b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
testEquality CardanoEra era
era CardanoEra era
era'

instance Bounded AnyCardanoEra where
  minBound :: AnyCardanoEra
minBound = CardanoEra ByronEra -> AnyCardanoEra
forall era. Typeable era => CardanoEra era -> AnyCardanoEra
AnyCardanoEra CardanoEra ByronEra
ByronEra
  maxBound :: AnyCardanoEra
maxBound = CardanoEra ConwayEra -> AnyCardanoEra
forall era. Typeable era => CardanoEra era -> AnyCardanoEra
AnyCardanoEra CardanoEra ConwayEra
ConwayEra

instance Enum AnyCardanoEra where
  -- [e..] = [e..maxBound]
  enumFrom :: AnyCardanoEra -> [AnyCardanoEra]
enumFrom AnyCardanoEra
e = AnyCardanoEra -> AnyCardanoEra -> [AnyCardanoEra]
forall a. Enum a => a -> a -> [a]
enumFromTo AnyCardanoEra
e AnyCardanoEra
forall a. Bounded a => a
maxBound

  fromEnum :: AnyCardanoEra -> Int
fromEnum = \case
    AnyCardanoEra CardanoEra era
ByronEra -> Int
0
    AnyCardanoEra CardanoEra era
ShelleyEra -> Int
1
    AnyCardanoEra CardanoEra era
AllegraEra -> Int
2
    AnyCardanoEra CardanoEra era
MaryEra -> Int
3
    AnyCardanoEra CardanoEra era
AlonzoEra -> Int
4
    AnyCardanoEra CardanoEra era
BabbageEra -> Int
5
    AnyCardanoEra CardanoEra era
ConwayEra -> Int
6

  toEnum :: Int -> AnyCardanoEra
toEnum = \case
    Int
0 -> CardanoEra ByronEra -> AnyCardanoEra
forall era. Typeable era => CardanoEra era -> AnyCardanoEra
AnyCardanoEra CardanoEra ByronEra
ByronEra
    Int
1 -> CardanoEra ShelleyEra -> AnyCardanoEra
forall era. Typeable era => CardanoEra era -> AnyCardanoEra
AnyCardanoEra CardanoEra ShelleyEra
ShelleyEra
    Int
2 -> CardanoEra AllegraEra -> AnyCardanoEra
forall era. Typeable era => CardanoEra era -> AnyCardanoEra
AnyCardanoEra CardanoEra AllegraEra
AllegraEra
    Int
3 -> CardanoEra MaryEra -> AnyCardanoEra
forall era. Typeable era => CardanoEra era -> AnyCardanoEra
AnyCardanoEra CardanoEra MaryEra
MaryEra
    Int
4 -> CardanoEra AlonzoEra -> AnyCardanoEra
forall era. Typeable era => CardanoEra era -> AnyCardanoEra
AnyCardanoEra CardanoEra AlonzoEra
AlonzoEra
    Int
5 -> CardanoEra BabbageEra -> AnyCardanoEra
forall era. Typeable era => CardanoEra era -> AnyCardanoEra
AnyCardanoEra CardanoEra BabbageEra
BabbageEra
    Int
6 -> CardanoEra ConwayEra -> AnyCardanoEra
forall era. Typeable era => CardanoEra era -> AnyCardanoEra
AnyCardanoEra CardanoEra ConwayEra
ConwayEra
    Int
n ->
      String -> AnyCardanoEra
forall a. HasCallStack => String -> a
error (String -> AnyCardanoEra) -> String -> AnyCardanoEra
forall a b. (a -> b) -> a -> b
$
        String
"AnyCardanoEra.toEnum: "
          String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
n
          String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
" does not correspond to any known enumerated era."

instance ToJSON AnyCardanoEra where
  toJSON :: AnyCardanoEra -> Value
toJSON (AnyCardanoEra CardanoEra era
era) = CardanoEra era -> Value
forall a. ToJSON a => a -> Value
toJSON CardanoEra era
era

instance FromJSON AnyCardanoEra where
  parseJSON :: Value -> Parser AnyCardanoEra
parseJSON =
    String
-> (Text -> Parser AnyCardanoEra) -> Value -> Parser AnyCardanoEra
forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText String
"AnyCardanoEra" ((Text -> Parser AnyCardanoEra) -> Value -> Parser AnyCardanoEra)
-> (Text -> Parser AnyCardanoEra) -> Value -> Parser AnyCardanoEra
forall a b. (a -> b) -> a -> b
$
      ( \case
          Right AnyCardanoEra
era -> AnyCardanoEra -> Parser AnyCardanoEra
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure AnyCardanoEra
era
          Left Text
era -> String -> Parser AnyCardanoEra
forall a. String -> Parser a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Parser AnyCardanoEra) -> String -> Parser AnyCardanoEra
forall a b. (a -> b) -> a -> b
$ String
"Failed to parse unknown era: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Text -> String
Text.unpack Text
era
      )
        (Either Text AnyCardanoEra -> Parser AnyCardanoEra)
-> (Text -> Either Text AnyCardanoEra)
-> Text
-> Parser AnyCardanoEra
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Either Text AnyCardanoEra
forall a. (IsString a, Eq a) => a -> Either a AnyCardanoEra
anyCardanoEraFromStringLike

cardanoEraToStringLike :: IsString a => CardanoEra era -> a
{-# INLINE cardanoEraToStringLike #-}
cardanoEraToStringLike :: forall a era. IsString a => CardanoEra era -> a
cardanoEraToStringLike = \case
  CardanoEra era
ByronEra -> a
"Byron"
  CardanoEra era
ShelleyEra -> a
"Shelley"
  CardanoEra era
AllegraEra -> a
"Allegra"
  CardanoEra era
MaryEra -> a
"Mary"
  CardanoEra era
AlonzoEra -> a
"Alonzo"
  CardanoEra era
BabbageEra -> a
"Babbage"
  CardanoEra era
ConwayEra -> a
"Conway"

anyCardanoEraFromStringLike :: (IsString a, Eq a) => a -> Either a AnyCardanoEra
{-# INLINE anyCardanoEraFromStringLike #-}
anyCardanoEraFromStringLike :: forall a. (IsString a, Eq a) => a -> Either a AnyCardanoEra
anyCardanoEraFromStringLike = \case
  a
"Byron" -> AnyCardanoEra -> Either a AnyCardanoEra
forall a. a -> Either a a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (AnyCardanoEra -> Either a AnyCardanoEra)
-> AnyCardanoEra -> Either a AnyCardanoEra
forall a b. (a -> b) -> a -> b
$ CardanoEra ByronEra -> AnyCardanoEra
forall era. Typeable era => CardanoEra era -> AnyCardanoEra
AnyCardanoEra CardanoEra ByronEra
ByronEra
  a
"Shelley" -> AnyCardanoEra -> Either a AnyCardanoEra
forall a. a -> Either a a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (AnyCardanoEra -> Either a AnyCardanoEra)
-> AnyCardanoEra -> Either a AnyCardanoEra
forall a b. (a -> b) -> a -> b
$ CardanoEra ShelleyEra -> AnyCardanoEra
forall era. Typeable era => CardanoEra era -> AnyCardanoEra
AnyCardanoEra CardanoEra ShelleyEra
ShelleyEra
  a
"Allegra" -> AnyCardanoEra -> Either a AnyCardanoEra
forall a. a -> Either a a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (AnyCardanoEra -> Either a AnyCardanoEra)
-> AnyCardanoEra -> Either a AnyCardanoEra
forall a b. (a -> b) -> a -> b
$ CardanoEra AllegraEra -> AnyCardanoEra
forall era. Typeable era => CardanoEra era -> AnyCardanoEra
AnyCardanoEra CardanoEra AllegraEra
AllegraEra
  a
"Mary" -> AnyCardanoEra -> Either a AnyCardanoEra
forall a. a -> Either a a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (AnyCardanoEra -> Either a AnyCardanoEra)
-> AnyCardanoEra -> Either a AnyCardanoEra
forall a b. (a -> b) -> a -> b
$ CardanoEra MaryEra -> AnyCardanoEra
forall era. Typeable era => CardanoEra era -> AnyCardanoEra
AnyCardanoEra CardanoEra MaryEra
MaryEra
  a
"Alonzo" -> AnyCardanoEra -> Either a AnyCardanoEra
forall a. a -> Either a a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (AnyCardanoEra -> Either a AnyCardanoEra)
-> AnyCardanoEra -> Either a AnyCardanoEra
forall a b. (a -> b) -> a -> b
$ CardanoEra AlonzoEra -> AnyCardanoEra
forall era. Typeable era => CardanoEra era -> AnyCardanoEra
AnyCardanoEra CardanoEra AlonzoEra
AlonzoEra
  a
"Babbage" -> AnyCardanoEra -> Either a AnyCardanoEra
forall a. a -> Either a a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (AnyCardanoEra -> Either a AnyCardanoEra)
-> AnyCardanoEra -> Either a AnyCardanoEra
forall a b. (a -> b) -> a -> b
$ CardanoEra BabbageEra -> AnyCardanoEra
forall era. Typeable era => CardanoEra era -> AnyCardanoEra
AnyCardanoEra CardanoEra BabbageEra
BabbageEra
  a
"Conway" -> AnyCardanoEra -> Either a AnyCardanoEra
forall a. a -> Either a a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (AnyCardanoEra -> Either a AnyCardanoEra)
-> AnyCardanoEra -> Either a AnyCardanoEra
forall a b. (a -> b) -> a -> b
$ CardanoEra ConwayEra -> AnyCardanoEra
forall era. Typeable era => CardanoEra era -> AnyCardanoEra
AnyCardanoEra CardanoEra ConwayEra
ConwayEra
  a
wrong -> a -> Either a AnyCardanoEra
forall a b. a -> Either a b
Left a
wrong

-- | Like the 'AnyCardanoEra' constructor but does not demand a 'IsCardanoEra'
-- class constraint.
anyCardanoEra :: CardanoEra era -> AnyCardanoEra
anyCardanoEra :: forall era. CardanoEra era -> AnyCardanoEra
anyCardanoEra = \case
  CardanoEra era
ByronEra -> CardanoEra ByronEra -> AnyCardanoEra
forall era. Typeable era => CardanoEra era -> AnyCardanoEra
AnyCardanoEra CardanoEra ByronEra
ByronEra
  CardanoEra era
ShelleyEra -> CardanoEra ShelleyEra -> AnyCardanoEra
forall era. Typeable era => CardanoEra era -> AnyCardanoEra
AnyCardanoEra CardanoEra ShelleyEra
ShelleyEra
  CardanoEra era
AllegraEra -> CardanoEra AllegraEra -> AnyCardanoEra
forall era. Typeable era => CardanoEra era -> AnyCardanoEra
AnyCardanoEra CardanoEra AllegraEra
AllegraEra
  CardanoEra era
MaryEra -> CardanoEra MaryEra -> AnyCardanoEra
forall era. Typeable era => CardanoEra era -> AnyCardanoEra
AnyCardanoEra CardanoEra MaryEra
MaryEra
  CardanoEra era
AlonzoEra -> CardanoEra AlonzoEra -> AnyCardanoEra
forall era. Typeable era => CardanoEra era -> AnyCardanoEra
AnyCardanoEra CardanoEra AlonzoEra
AlonzoEra
  CardanoEra era
BabbageEra -> CardanoEra BabbageEra -> AnyCardanoEra
forall era. Typeable era => CardanoEra era -> AnyCardanoEra
AnyCardanoEra CardanoEra BabbageEra
BabbageEra
  CardanoEra era
ConwayEra -> CardanoEra ConwayEra -> AnyCardanoEra
forall era. Typeable era => CardanoEra era -> AnyCardanoEra
AnyCardanoEra CardanoEra ConwayEra
ConwayEra

-- | This pairs up some era-dependent type with a 'CardanoEra' value that tells
-- us what era it is, but hides the era type. This is useful when the era is
-- not statically known, for example when deserialising from a file.
data InAnyCardanoEra thing where
  InAnyCardanoEra
    :: Typeable era
    => CardanoEra era
    -> thing era
    -> InAnyCardanoEra thing

inAnyCardanoEra
  :: ()
  => CardanoEra era
  -> thing era
  -> InAnyCardanoEra thing
inAnyCardanoEra :: forall era (thing :: * -> *).
CardanoEra era -> thing era -> InAnyCardanoEra thing
inAnyCardanoEra CardanoEra era
era thing era
a =
  CardanoEra era
-> (CardanoEraConstraints era => InAnyCardanoEra thing)
-> InAnyCardanoEra thing
forall era a.
CardanoEra era -> (CardanoEraConstraints era => a) -> a
cardanoEraConstraints CardanoEra era
era ((CardanoEraConstraints era => InAnyCardanoEra thing)
 -> InAnyCardanoEra thing)
-> (CardanoEraConstraints era => InAnyCardanoEra thing)
-> InAnyCardanoEra thing
forall a b. (a -> b) -> a -> b
$ CardanoEra era -> thing era -> InAnyCardanoEra thing
forall era (thing :: * -> *).
Typeable era =>
CardanoEra era -> thing era -> InAnyCardanoEra thing
InAnyCardanoEra CardanoEra era
era thing era
a

-- ----------------------------------------------------------------------------
-- Conversion to ledger library types
--

-- | A type family that connects our era type tags to equivalent type tags used
-- in the ledger library.
--
-- This type mapping  connect types from this API with types in the
-- ledger library which allows writing conversion functions in a more generic
-- way.
type family CardanoLedgerEra era = ledgerera | ledgerera -> era where
  CardanoLedgerEra ByronEra = L.ByronEra L.StandardCrypto
  CardanoLedgerEra ShelleyEra = L.ShelleyEra L.StandardCrypto
  CardanoLedgerEra AllegraEra = L.AllegraEra L.StandardCrypto
  CardanoLedgerEra MaryEra = L.MaryEra L.StandardCrypto
  CardanoLedgerEra AlonzoEra = L.AlonzoEra L.StandardCrypto
  CardanoLedgerEra BabbageEra = L.BabbageEra L.StandardCrypto
  CardanoLedgerEra ConwayEra = L.ConwayEra L.StandardCrypto