module Tendermint.SDK.Modules.Bank.Messages where

import           Control.Lens                 (Wrapped (..), from, iso, view,
                                               (&), (.~), (^.))
import           Data.Bifunctor               (bimap)
import qualified Data.ProtoLens               as P
import           Data.String.Conversions      (cs)
import           Data.Validation              (Validation (..))
import           GHC.Generics                 (Generic)
import qualified Proto.Modules.Bank           as B
import qualified Proto.Modules.Bank_Fields    as B
import           Tendermint.SDK.Codec         (HasCodec (..))
import           Tendermint.SDK.Modules.Auth  (Amount (..), CoinId (..))
import           Tendermint.SDK.Types.Address (Address, addressFromBytes,
                                               addressToBytes)
import           Tendermint.SDK.Types.Message (HasMessageType (..),
                                               ValidateMessage (..))

data TransferMsg = TransferMsg
  { TransferMsg -> Address
transferTo     :: Address
  , TransferMsg -> Address
transferFrom   :: Address
  , TransferMsg -> CoinId
transferCoinId :: CoinId
  , TransferMsg -> Amount
transferAmount :: Amount
  } deriving (TransferMsg -> TransferMsg -> Bool
(TransferMsg -> TransferMsg -> Bool)
-> (TransferMsg -> TransferMsg -> Bool) -> Eq TransferMsg
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TransferMsg -> TransferMsg -> Bool
$c/= :: TransferMsg -> TransferMsg -> Bool
== :: TransferMsg -> TransferMsg -> Bool
$c== :: TransferMsg -> TransferMsg -> Bool
Eq, Int -> TransferMsg -> ShowS
[TransferMsg] -> ShowS
TransferMsg -> String
(Int -> TransferMsg -> ShowS)
-> (TransferMsg -> String)
-> ([TransferMsg] -> ShowS)
-> Show TransferMsg
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TransferMsg] -> ShowS
$cshowList :: [TransferMsg] -> ShowS
show :: TransferMsg -> String
$cshow :: TransferMsg -> String
showsPrec :: Int -> TransferMsg -> ShowS
$cshowsPrec :: Int -> TransferMsg -> ShowS
Show, (forall x. TransferMsg -> Rep TransferMsg x)
-> (forall x. Rep TransferMsg x -> TransferMsg)
-> Generic TransferMsg
forall x. Rep TransferMsg x -> TransferMsg
forall x. TransferMsg -> Rep TransferMsg x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep TransferMsg x -> TransferMsg
$cfrom :: forall x. TransferMsg -> Rep TransferMsg x
Generic)

instance Wrapped TransferMsg where
  type Unwrapped TransferMsg = B.Transfer

  _Wrapped' :: p (Unwrapped TransferMsg) (f (Unwrapped TransferMsg))
-> p TransferMsg (f TransferMsg)
_Wrapped' = (TransferMsg -> Transfer)
-> (Transfer -> TransferMsg)
-> Iso TransferMsg TransferMsg Transfer Transfer
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso TransferMsg -> Transfer
forall b.
(Message b, HasField b "amount" Word64, HasField b "cid" Text,
 HasField b "from" ByteString, HasField b "to" ByteString) =>
TransferMsg -> b
t Transfer -> TransferMsg
forall s.
(HasField s "amount" Word64, HasField s "cid" Text,
 HasField s "from" ByteString, HasField s "to" ByteString) =>
s -> TransferMsg
f
   where
    t :: TransferMsg -> b
t TransferMsg {..} =
      b
forall msg. Message msg => msg
P.defMessage
        b -> (b -> b) -> b
forall a b. a -> (a -> b) -> b
& LensLike' Identity b ByteString
forall (f :: * -> *) s a.
(Functor f, HasField s "to" a) =>
LensLike' f s a
B.to LensLike' Identity b ByteString -> ByteString -> b -> b
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Address -> ByteString
addressToBytes Address
transferTo
        b -> (b -> b) -> b
forall a b. a -> (a -> b) -> b
& LensLike' Identity b ByteString
forall (f :: * -> *) s a.
(Functor f, HasField s "from" a) =>
LensLike' f s a
B.from LensLike' Identity b ByteString -> ByteString -> b -> b
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Address -> ByteString
addressToBytes Address
transferFrom
        b -> (b -> b) -> b
forall a b. a -> (a -> b) -> b
& LensLike' Identity b Text
forall (f :: * -> *) s a.
(Functor f, HasField s "cid" a) =>
LensLike' f s a
B.cid LensLike' Identity b Text -> Text -> b -> b
forall s t a b. ASetter s t a b -> b -> s -> t
.~ CoinId -> Text
unCoinId CoinId
transferCoinId
        b -> (b -> b) -> b
forall a b. a -> (a -> b) -> b
& LensLike' Identity b Word64
forall (f :: * -> *) s a.
(Functor f, HasField s "amount" a) =>
LensLike' f s a
B.amount LensLike' Identity b Word64 -> Word64 -> b -> b
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Amount -> Word64
unAmount Amount
transferAmount
    f :: s -> TransferMsg
f message :: s
message = TransferMsg :: Address -> Address -> CoinId -> Amount -> TransferMsg
TransferMsg
      { transferTo :: Address
transferTo = ByteString -> Address
addressFromBytes (ByteString -> Address) -> ByteString -> Address
forall a b. (a -> b) -> a -> b
$ s
message s -> Getting ByteString s ByteString -> ByteString
forall s a. s -> Getting a s a -> a
^. Getting ByteString s ByteString
forall (f :: * -> *) s a.
(Functor f, HasField s "to" a) =>
LensLike' f s a
B.to
      , transferFrom :: Address
transferFrom = ByteString -> Address
addressFromBytes (ByteString -> Address) -> ByteString -> Address
forall a b. (a -> b) -> a -> b
$ s
message s -> Getting ByteString s ByteString -> ByteString
forall s a. s -> Getting a s a -> a
^. Getting ByteString s ByteString
forall (f :: * -> *) s a.
(Functor f, HasField s "from" a) =>
LensLike' f s a
B.from
      , transferCoinId :: CoinId
transferCoinId = Text -> CoinId
CoinId (Text -> CoinId) -> Text -> CoinId
forall a b. (a -> b) -> a -> b
$ s
message s -> Getting Text s Text -> Text
forall s a. s -> Getting a s a -> a
^. Getting Text s Text
forall (f :: * -> *) s a.
(Functor f, HasField s "cid" a) =>
LensLike' f s a
B.cid
      , transferAmount :: Amount
transferAmount = Word64 -> Amount
Amount (Word64 -> Amount) -> Word64 -> Amount
forall a b. (a -> b) -> a -> b
$ s
message s -> Getting Word64 s Word64 -> Word64
forall s a. s -> Getting a s a -> a
^. Getting Word64 s Word64
forall (f :: * -> *) s a.
(Functor f, HasField s "amount" a) =>
LensLike' f s a
B.amount
      }

instance HasMessageType TransferMsg where
  messageType :: Proxy TransferMsg -> Text
messageType _ = "TransferMsg"

instance HasCodec TransferMsg where
  encode :: TransferMsg -> ByteString
encode = Transfer -> ByteString
forall msg. Message msg => msg -> ByteString
P.encodeMessage (Transfer -> ByteString)
-> (TransferMsg -> Transfer) -> TransferMsg -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting Transfer TransferMsg Transfer -> TransferMsg -> Transfer
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Transfer TransferMsg Transfer
forall s. Wrapped s => Iso' s (Unwrapped s)
_Wrapped'
  decode :: ByteString -> Either Text TransferMsg
decode = (String -> Text)
-> (Transfer -> TransferMsg)
-> Either String Transfer
-> Either Text TransferMsg
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap String -> Text
forall a b. ConvertibleStrings a b => a -> b
cs (Getting TransferMsg Transfer TransferMsg -> Transfer -> TransferMsg
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (Getting TransferMsg Transfer TransferMsg
 -> Transfer -> TransferMsg)
-> Getting TransferMsg Transfer TransferMsg
-> Transfer
-> TransferMsg
forall a b. (a -> b) -> a -> b
$ AnIso TransferMsg TransferMsg Transfer Transfer
-> Iso Transfer Transfer TransferMsg TransferMsg
forall s t a b. AnIso s t a b -> Iso b a t s
from AnIso TransferMsg TransferMsg Transfer Transfer
forall s. Wrapped s => Iso' s (Unwrapped s)
_Wrapped') (Either String Transfer -> Either Text TransferMsg)
-> (ByteString -> Either String Transfer)
-> ByteString
-> Either Text TransferMsg
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String Transfer
forall msg. Message msg => ByteString -> Either String msg
P.decodeMessage

instance ValidateMessage TransferMsg where
  validateMessage :: Msg TransferMsg -> Validation [MessageSemanticError] ()
validateMessage _ = () -> Validation [MessageSemanticError] ()
forall err a. a -> Validation err a
Success ()

--------------------------------------------------------------------------------

data BurnMsg = BurnMsg
  { BurnMsg -> Address
burnAddress :: Address
  , BurnMsg -> CoinId
burnCoinId  :: CoinId
  , BurnMsg -> Amount
burnAmount  :: Amount
  } deriving (BurnMsg -> BurnMsg -> Bool
(BurnMsg -> BurnMsg -> Bool)
-> (BurnMsg -> BurnMsg -> Bool) -> Eq BurnMsg
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BurnMsg -> BurnMsg -> Bool
$c/= :: BurnMsg -> BurnMsg -> Bool
== :: BurnMsg -> BurnMsg -> Bool
$c== :: BurnMsg -> BurnMsg -> Bool
Eq, Int -> BurnMsg -> ShowS
[BurnMsg] -> ShowS
BurnMsg -> String
(Int -> BurnMsg -> ShowS)
-> (BurnMsg -> String) -> ([BurnMsg] -> ShowS) -> Show BurnMsg
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [BurnMsg] -> ShowS
$cshowList :: [BurnMsg] -> ShowS
show :: BurnMsg -> String
$cshow :: BurnMsg -> String
showsPrec :: Int -> BurnMsg -> ShowS
$cshowsPrec :: Int -> BurnMsg -> ShowS
Show, (forall x. BurnMsg -> Rep BurnMsg x)
-> (forall x. Rep BurnMsg x -> BurnMsg) -> Generic BurnMsg
forall x. Rep BurnMsg x -> BurnMsg
forall x. BurnMsg -> Rep BurnMsg x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep BurnMsg x -> BurnMsg
$cfrom :: forall x. BurnMsg -> Rep BurnMsg x
Generic)

instance Wrapped BurnMsg where
  type Unwrapped BurnMsg = B.Burn

  _Wrapped' :: p (Unwrapped BurnMsg) (f (Unwrapped BurnMsg))
-> p BurnMsg (f BurnMsg)
_Wrapped' = (BurnMsg -> Burn)
-> (Burn -> BurnMsg) -> Iso BurnMsg BurnMsg Burn Burn
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso BurnMsg -> Burn
forall b.
(Message b, HasField b "address" ByteString,
 HasField b "amount" Word64, HasField b "cid" Text) =>
BurnMsg -> b
t Burn -> BurnMsg
forall s.
(HasField s "address" ByteString, HasField s "amount" Word64,
 HasField s "cid" Text) =>
s -> BurnMsg
f
   where
    t :: BurnMsg -> b
t BurnMsg {..} =
      b
forall msg. Message msg => msg
P.defMessage
        b -> (b -> b) -> b
forall a b. a -> (a -> b) -> b
& LensLike' Identity b ByteString
forall (f :: * -> *) s a.
(Functor f, HasField s "address" a) =>
LensLike' f s a
B.address LensLike' Identity b ByteString -> ByteString -> b -> b
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Address -> ByteString
addressToBytes Address
burnAddress
        b -> (b -> b) -> b
forall a b. a -> (a -> b) -> b
& LensLike' Identity b Text
forall (f :: * -> *) s a.
(Functor f, HasField s "cid" a) =>
LensLike' f s a
B.cid LensLike' Identity b Text -> Text -> b -> b
forall s t a b. ASetter s t a b -> b -> s -> t
.~ CoinId -> Text
unCoinId CoinId
burnCoinId
        b -> (b -> b) -> b
forall a b. a -> (a -> b) -> b
& LensLike' Identity b Word64
forall (f :: * -> *) s a.
(Functor f, HasField s "amount" a) =>
LensLike' f s a
B.amount LensLike' Identity b Word64 -> Word64 -> b -> b
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Amount -> Word64
unAmount Amount
burnAmount
    f :: s -> BurnMsg
f message :: s
message = BurnMsg :: Address -> CoinId -> Amount -> BurnMsg
BurnMsg
      { burnAddress :: Address
burnAddress = ByteString -> Address
addressFromBytes (ByteString -> Address) -> ByteString -> Address
forall a b. (a -> b) -> a -> b
$ s
message s -> Getting ByteString s ByteString -> ByteString
forall s a. s -> Getting a s a -> a
^. Getting ByteString s ByteString
forall (f :: * -> *) s a.
(Functor f, HasField s "address" a) =>
LensLike' f s a
B.address
      , burnCoinId :: CoinId
burnCoinId = Text -> CoinId
CoinId (Text -> CoinId) -> Text -> CoinId
forall a b. (a -> b) -> a -> b
$ s
message s -> Getting Text s Text -> Text
forall s a. s -> Getting a s a -> a
^. Getting Text s Text
forall (f :: * -> *) s a.
(Functor f, HasField s "cid" a) =>
LensLike' f s a
B.cid
      , burnAmount :: Amount
burnAmount = Word64 -> Amount
Amount (Word64 -> Amount) -> Word64 -> Amount
forall a b. (a -> b) -> a -> b
$ s
message s -> Getting Word64 s Word64 -> Word64
forall s a. s -> Getting a s a -> a
^. Getting Word64 s Word64
forall (f :: * -> *) s a.
(Functor f, HasField s "amount" a) =>
LensLike' f s a
B.amount
      }

instance HasMessageType BurnMsg where
  messageType :: Proxy BurnMsg -> Text
messageType _ = "BurnMsg"

instance HasCodec BurnMsg where
  encode :: BurnMsg -> ByteString
encode = Burn -> ByteString
forall msg. Message msg => msg -> ByteString
P.encodeMessage (Burn -> ByteString) -> (BurnMsg -> Burn) -> BurnMsg -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting Burn BurnMsg Burn -> BurnMsg -> Burn
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Burn BurnMsg Burn
forall s. Wrapped s => Iso' s (Unwrapped s)
_Wrapped'
  decode :: ByteString -> Either Text BurnMsg
decode = (String -> Text)
-> (Burn -> BurnMsg) -> Either String Burn -> Either Text BurnMsg
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap String -> Text
forall a b. ConvertibleStrings a b => a -> b
cs (Getting BurnMsg Burn BurnMsg -> Burn -> BurnMsg
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (Getting BurnMsg Burn BurnMsg -> Burn -> BurnMsg)
-> Getting BurnMsg Burn BurnMsg -> Burn -> BurnMsg
forall a b. (a -> b) -> a -> b
$ AnIso BurnMsg BurnMsg Burn Burn -> Iso Burn Burn BurnMsg BurnMsg
forall s t a b. AnIso s t a b -> Iso b a t s
from AnIso BurnMsg BurnMsg Burn Burn
forall s. Wrapped s => Iso' s (Unwrapped s)
_Wrapped') (Either String Burn -> Either Text BurnMsg)
-> (ByteString -> Either String Burn)
-> ByteString
-> Either Text BurnMsg
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String Burn
forall msg. Message msg => ByteString -> Either String msg
P.decodeMessage

instance ValidateMessage BurnMsg where
  validateMessage :: Msg BurnMsg -> Validation [MessageSemanticError] ()
validateMessage _ = () -> Validation [MessageSemanticError] ()
forall err a. a -> Validation err a
Success ()