{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE StandaloneDeriving         #-}
{-# LANGUAGE UndecidableInstances       #-}

module Cardano.Chain.Genesis.AvvmBalances
  ( GenesisAvvmBalances(..)
  )
where

import Cardano.Prelude

import NoThunks.Class (NoThunks (..))
import Text.JSON.Canonical (FromJSON(..), ToJSON(..))

import Cardano.Chain.Common (Lovelace)
import Cardano.Crypto.Signing.Redeem (CompactRedeemVerificationKey)


-- | Predefined balances of AVVM (Ada Voucher Vending Machine) entries.
-- People who purchased Ada at a pre-sale were issued a certificate during
-- the pre-sale period. These certificates allow customers to redeem ADA.
newtype GenesisAvvmBalances = GenesisAvvmBalances
  { GenesisAvvmBalances -> Map CompactRedeemVerificationKey Lovelace
unGenesisAvvmBalances :: Map CompactRedeemVerificationKey Lovelace
  } deriving (Int -> GenesisAvvmBalances -> ShowS
[GenesisAvvmBalances] -> ShowS
GenesisAvvmBalances -> String
(Int -> GenesisAvvmBalances -> ShowS)
-> (GenesisAvvmBalances -> String)
-> ([GenesisAvvmBalances] -> ShowS)
-> Show GenesisAvvmBalances
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [GenesisAvvmBalances] -> ShowS
$cshowList :: [GenesisAvvmBalances] -> ShowS
show :: GenesisAvvmBalances -> String
$cshow :: GenesisAvvmBalances -> String
showsPrec :: Int -> GenesisAvvmBalances -> ShowS
$cshowsPrec :: Int -> GenesisAvvmBalances -> ShowS
Show, GenesisAvvmBalances -> GenesisAvvmBalances -> Bool
(GenesisAvvmBalances -> GenesisAvvmBalances -> Bool)
-> (GenesisAvvmBalances -> GenesisAvvmBalances -> Bool)
-> Eq GenesisAvvmBalances
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: GenesisAvvmBalances -> GenesisAvvmBalances -> Bool
$c/= :: GenesisAvvmBalances -> GenesisAvvmBalances -> Bool
== :: GenesisAvvmBalances -> GenesisAvvmBalances -> Bool
$c== :: GenesisAvvmBalances -> GenesisAvvmBalances -> Bool
Eq, b -> GenesisAvvmBalances -> GenesisAvvmBalances
NonEmpty GenesisAvvmBalances -> GenesisAvvmBalances
GenesisAvvmBalances -> GenesisAvvmBalances -> GenesisAvvmBalances
(GenesisAvvmBalances -> GenesisAvvmBalances -> GenesisAvvmBalances)
-> (NonEmpty GenesisAvvmBalances -> GenesisAvvmBalances)
-> (forall b.
    Integral b =>
    b -> GenesisAvvmBalances -> GenesisAvvmBalances)
-> Semigroup GenesisAvvmBalances
forall b.
Integral b =>
b -> GenesisAvvmBalances -> GenesisAvvmBalances
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: b -> GenesisAvvmBalances -> GenesisAvvmBalances
$cstimes :: forall b.
Integral b =>
b -> GenesisAvvmBalances -> GenesisAvvmBalances
sconcat :: NonEmpty GenesisAvvmBalances -> GenesisAvvmBalances
$csconcat :: NonEmpty GenesisAvvmBalances -> GenesisAvvmBalances
<> :: GenesisAvvmBalances -> GenesisAvvmBalances -> GenesisAvvmBalances
$c<> :: GenesisAvvmBalances -> GenesisAvvmBalances -> GenesisAvvmBalances
Semigroup, Context -> GenesisAvvmBalances -> IO (Maybe ThunkInfo)
Proxy GenesisAvvmBalances -> String
(Context -> GenesisAvvmBalances -> IO (Maybe ThunkInfo))
-> (Context -> GenesisAvvmBalances -> IO (Maybe ThunkInfo))
-> (Proxy GenesisAvvmBalances -> String)
-> NoThunks GenesisAvvmBalances
forall a.
(Context -> a -> IO (Maybe ThunkInfo))
-> (Context -> a -> IO (Maybe ThunkInfo))
-> (Proxy a -> String)
-> NoThunks a
showTypeOf :: Proxy GenesisAvvmBalances -> String
$cshowTypeOf :: Proxy GenesisAvvmBalances -> String
wNoThunks :: Context -> GenesisAvvmBalances -> IO (Maybe ThunkInfo)
$cwNoThunks :: Context -> GenesisAvvmBalances -> IO (Maybe ThunkInfo)
noThunks :: Context -> GenesisAvvmBalances -> IO (Maybe ThunkInfo)
$cnoThunks :: Context -> GenesisAvvmBalances -> IO (Maybe ThunkInfo)
NoThunks)

instance Monad m => ToJSON m GenesisAvvmBalances where
    toJSON :: GenesisAvvmBalances -> m JSValue
toJSON = Map CompactRedeemVerificationKey Lovelace -> m JSValue
forall (m :: * -> *) a. ToJSON m a => a -> m JSValue
toJSON (Map CompactRedeemVerificationKey Lovelace -> m JSValue)
-> (GenesisAvvmBalances
    -> Map CompactRedeemVerificationKey Lovelace)
-> GenesisAvvmBalances
-> m JSValue
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. GenesisAvvmBalances -> Map CompactRedeemVerificationKey Lovelace
unGenesisAvvmBalances

instance MonadError SchemaError m => FromJSON m GenesisAvvmBalances where
    -- | Unfortunately, because @canonical-json@ doesn't utilize operations from
    -- "Data.Map.Strict" but only those from "Data.Map.Lazy" (i.e. 'fromJSON'
    -- will return a 'Map' that is not necessarily strict in its values), we
    -- need to be careful in order to ensure that we're still dealing with a
    -- 'Map' that's strict in both its keys and values.
    --
    -- To remedy this, we use 'forceElemsToWHNF' from "Cardano.Prelude" to
    -- convert the 'Map' to one that is now guaranteed to be strict in both
    -- its keys and values.
    --
    -- n.b. both the strict and lazy 'Map' modules utilize the same 'Map' data
    -- type which is what makes something like this possible.
    fromJSON :: JSValue -> m GenesisAvvmBalances
fromJSON = (Map CompactRedeemVerificationKey Lovelace -> GenesisAvvmBalances)
-> m (Map CompactRedeemVerificationKey Lovelace)
-> m GenesisAvvmBalances
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Map CompactRedeemVerificationKey Lovelace -> GenesisAvvmBalances
GenesisAvvmBalances (Map CompactRedeemVerificationKey Lovelace -> GenesisAvvmBalances)
-> (Map CompactRedeemVerificationKey Lovelace
    -> Map CompactRedeemVerificationKey Lovelace)
-> Map CompactRedeemVerificationKey Lovelace
-> GenesisAvvmBalances
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Map CompactRedeemVerificationKey Lovelace
-> Map CompactRedeemVerificationKey Lovelace
forall (t :: * -> *) a. Foldable t => t a -> t a
forceElemsToWHNF) (m (Map CompactRedeemVerificationKey Lovelace)
 -> m GenesisAvvmBalances)
-> (JSValue -> m (Map CompactRedeemVerificationKey Lovelace))
-> JSValue
-> m GenesisAvvmBalances
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. JSValue -> m (Map CompactRedeemVerificationKey Lovelace)
forall (m :: * -> *) a. FromJSON m a => JSValue -> m a
fromJSON