{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
module Network.Polkadot.Call where
import Codec.Scale (Decode, Encode, Generic, decode)
import Control.Monad.Fail (MonadFail)
import Data.List (findIndex)
import Data.Text (Text)
import Data.Word (Word8)
import qualified GHC.Generics as GHC (Generic)
import Network.JsonRpc.TinyClient (JsonRpc)
import Network.Polkadot.Metadata (MetadataVersioned (V13),
metadata)
import Network.Polkadot.Metadata.V13 (moduleCalls, moduleName,
modules)
import Network.Polkadot.Metadata.V9 (functionName)
import Network.Polkadot.Rpc.State (getMetadata)
data Call a = Call !Word8 !Word8 !a
deriving (Call a -> Call a -> Bool
(Call a -> Call a -> Bool)
-> (Call a -> Call a -> Bool) -> Eq (Call a)
forall a. Eq a => Call a -> Call a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => Call a -> Call a -> Bool
== :: Call a -> Call a -> Bool
$c/= :: forall a. Eq a => Call a -> Call a -> Bool
/= :: Call a -> Call a -> Bool
Eq, Int -> Call a -> ShowS
[Call a] -> ShowS
Call a -> String
(Int -> Call a -> ShowS)
-> (Call a -> String) -> ([Call a] -> ShowS) -> Show (Call a)
forall a. Show a => Int -> Call a -> ShowS
forall a. Show a => [Call a] -> ShowS
forall a. Show a => Call a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> Call a -> ShowS
showsPrec :: Int -> Call a -> ShowS
$cshow :: forall a. Show a => Call a -> String
show :: Call a -> String
$cshowList :: forall a. Show a => [Call a] -> ShowS
showList :: [Call a] -> ShowS
Show, All SListI (Code (Call a))
All SListI (Code (Call a)) =>
(Call a -> Rep (Call a))
-> (Rep (Call a) -> Call a) -> Generic (Call a)
Rep (Call a) -> Call a
Call a -> Rep (Call a)
forall a. All SListI (Code (Call a))
forall a.
All SListI (Code a) =>
(a -> Rep a) -> (Rep a -> a) -> Generic a
forall a. Rep (Call a) -> Call a
forall a. Call a -> Rep (Call a)
$cfrom :: forall a. Call a -> Rep (Call a)
from :: Call a -> Rep (Call a)
$cto :: forall a. Rep (Call a) -> Call a
to :: Rep (Call a) -> Call a
Generic, (forall x. Call a -> Rep (Call a) x)
-> (forall x. Rep (Call a) x -> Call a) -> Generic (Call a)
forall x. Rep (Call a) x -> Call a
forall x. Call a -> Rep (Call a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Call a) x -> Call a
forall a x. Call a -> Rep (Call a) x
$cfrom :: forall a x. Call a -> Rep (Call a) x
from :: forall x. Call a -> Rep (Call a) x
$cto :: forall a x. Rep (Call a) x -> Call a
to :: forall x. Rep (Call a) x -> Call a
GHC.Generic, Putter (Call a)
Putter (Call a) -> Encode (Call a)
forall a. Encode a => Putter (Call a)
forall a. Putter a -> Encode a
$cput :: forall a. Encode a => Putter (Call a)
put :: Putter (Call a)
Encode, Get (Call a)
Get (Call a) -> Decode (Call a)
forall a. Get a -> Decode a
forall a. Decode a => Get (Call a)
$cget :: forall a. Decode a => Get (Call a)
get :: Get (Call a)
Decode)
new_call :: (Encode a, Decode a, JsonRpc m, MonadFail m)
=> Text
-> Text
-> a
-> m (Call a)
new_call :: forall a (m :: * -> *).
(Encode a, Decode a, JsonRpc m, MonadFail m) =>
Text -> Text -> a -> m (Call a)
new_call Text
modName Text
funName a
args = do
Right (V13 Metadata
meta) <- ((Metadata -> MetadataVersioned)
-> Either String Metadata -> Either String MetadataVersioned
forall a b. (a -> b) -> Either String a -> Either String b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Metadata -> MetadataVersioned
metadata (Either String Metadata -> Either String MetadataVersioned)
-> (HexString -> Either String Metadata)
-> HexString
-> Either String MetadataVersioned
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HexString -> Either String Metadata
forall ba a.
(ByteArrayAccess ba, Decode a) =>
ba -> Either String a
decode) (HexString -> Either String MetadataVersioned)
-> m HexString -> m (Either String MetadataVersioned)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m HexString
forall (m :: * -> *). JsonRpc m => m HexString
getMetadata
case (ModuleMetadata -> Bool) -> [ModuleMetadata] -> Maybe Int
forall a. (a -> Bool) -> [a] -> Maybe Int
findIndex ((Text
modName Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
==) (Text -> Bool)
-> (ModuleMetadata -> Text) -> ModuleMetadata -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ModuleMetadata -> Text
moduleName) (Metadata -> [ModuleMetadata]
modules Metadata
meta) of
Maybe Int
Nothing -> String -> m (Call a)
forall a. String -> m a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> m (Call a)) -> String -> m (Call a)
forall a b. (a -> b) -> a -> b
$ String
"module " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Text -> String
forall a. Show a => a -> String
show Text
modName String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
" not found"
Just Int
modIx ->
case (FunctionMetadata -> Bool) -> [FunctionMetadata] -> Maybe Int
forall a. (a -> Bool) -> [a] -> Maybe Int
findIndex ((Text
funName Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
==) (Text -> Bool)
-> (FunctionMetadata -> Text) -> FunctionMetadata -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FunctionMetadata -> Text
functionName) ([FunctionMetadata] -> Maybe Int)
-> Maybe [FunctionMetadata] -> Maybe Int
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< ModuleMetadata -> Maybe [FunctionMetadata]
moduleCalls (Metadata -> [ModuleMetadata]
modules Metadata
meta [ModuleMetadata] -> Int -> ModuleMetadata
forall a. HasCallStack => [a] -> Int -> a
!! Int
modIx) of
Maybe Int
Nothing -> String -> m (Call a)
forall a. String -> m a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> m (Call a)) -> String -> m (Call a)
forall a b. (a -> b) -> a -> b
$ String
"function " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Text -> String
forall a. Show a => a -> String
show Text
funName String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
" not found"
Just Int
funIx -> Call a -> m (Call a)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Call a -> m (Call a)) -> Call a -> m (Call a)
forall a b. (a -> b) -> a -> b
$ Word8 -> Word8 -> a -> Call a
forall a. Word8 -> Word8 -> a -> Call a
Call (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
modIx) (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
funIx) a
args