packages feed

web3-polkadot-1.0.1.0: src/Network/Polkadot/Call.hs

{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric  #-}

-- |
-- Module      :  Network.Polkadot.Call
-- Copyright   :  Aleksandr Krupenkin 2016-2024
-- License     :  Apache-2.0
--
-- Maintainer  :  mail@akru.me
-- Stability   :  experimental
-- Portability :  unportable
--
--

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)

-- | Call function of module using standard substrate extrionsic.
data Call a = Call !Word8 !Word8 !a
    deriving (Eq, Show, Generic, GHC.Generic, Encode, Decode)

-- | Create 'Call' type from text-encoded module and function.
new_call :: (Encode a, Decode a, JsonRpc m, MonadFail m)
         => Text
         -- ^ Module name.
         -> Text
         -- ^ Function name.
         -> a
         -- ^ Tuple of arguments.
         -> m (Call a)
new_call modName funName args = do
    Right (V13 meta) <- (fmap metadata . decode) <$> getMetadata
    case findIndex ((modName ==) . moduleName) (modules meta) of
        Nothing -> fail $ "module " <> show modName <> " not found"
        Just modIx ->
            case findIndex ((funName ==) . functionName) =<< moduleCalls (modules meta !! modIx) of
                Nothing -> fail $ "function " <> show funName <> " not found"
                Just funIx -> return $ Call (fromIntegral modIx) (fromIntegral funIx) args