module Tendermint.SDK.Modules.Bank.Query where

import           Control.Lens                       ((^.))
import qualified Data.ByteArray.Base64String        as Base64
import           Polysemy
import           Servant.API
import qualified Tendermint.SDK.BaseApp             as BaseApp
import           Tendermint.SDK.BaseApp.Query       (QueryArgs (..))
import qualified Tendermint.SDK.Modules.Auth        as Auth
import           Tendermint.SDK.Modules.Bank.Keeper (BankKeeper, getBalance)
import           Tendermint.SDK.Types.Address       (Address)

--------------------------------------------------------------------------------
-- | Query Api
--------------------------------------------------------------------------------

type GetAddressCoinBalance =
     "balance"
  :> BaseApp.QA Address
  :> QueryParam' '[Required, Strict] "coin_id" Auth.CoinId
  :> BaseApp.Leaf Auth.Coin

getAddressCoinBalance
  :: Member BankKeeper r
  => QueryArgs Address
  -> Auth.CoinId
  -> Sem r (BaseApp.QueryResult Auth.Coin)
getAddressCoinBalance :: QueryArgs Address -> CoinId -> Sem r (QueryResult Coin)
getAddressCoinBalance (QueryArgs _ address :: Address
address _) cid :: CoinId
cid = do
  Coin
coin <- Address -> CoinId -> Sem r Coin
forall (r :: [Effect]).
MemberWithError BankKeeper r =>
Address -> CoinId -> Sem r Coin
getBalance Address
address CoinId
cid
  QueryResult Coin -> Sem r (QueryResult Coin)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (QueryResult Coin -> Sem r (QueryResult Coin))
-> QueryResult Coin -> Sem r (QueryResult Coin)
forall a b. (a -> b) -> a -> b
$ QueryResult :: forall a.
a -> Int64 -> Base64String -> Maybe Proof -> Int64 -> QueryResult a
BaseApp.QueryResult
    { queryResultData :: Coin
queryResultData = Coin
coin
    , queryResultIndex :: Int64
queryResultIndex = 0
    , queryResultKey :: Base64String
queryResultKey = ByteString -> Base64String
forall ba. ByteArrayAccess ba => ba -> Base64String
Base64.fromBytes (ByteString -> Base64String) -> ByteString -> Base64String
forall a b. (a -> b) -> a -> b
$ Address
address Address -> Getting ByteString Address ByteString -> ByteString
forall s a. s -> Getting a s a -> a
^. Getting ByteString Address ByteString
forall k. RawKey k => Iso' k ByteString
BaseApp.rawKey
    , queryResultProof :: Maybe Proof
queryResultProof  = Maybe Proof
forall a. Maybe a
Nothing
    , queryResultHeight :: Int64
queryResultHeight = 0
    }

type QueryApi = GetAddressCoinBalance

querier
  :: forall r.
     Member BankKeeper r
  => BaseApp.RouteQ QueryApi r
querier :: RouteQ QueryApi r
querier = RouteQ QueryApi r
forall (r :: [Effect]).
Member BankKeeper r =>
QueryArgs Address -> CoinId -> Sem r (QueryResult Coin)
getAddressCoinBalance