{-# LANGUAGE FlexibleContexts #-}
module Network.Polkadot.Extrinsic
( Extrinsic
, SignedExtra
, sign_and_send
, mortal_max
, new_extra'
, new_extra
) where
import Codec.Scale (Compact (..),
Encode,
encode)
import Data.ByteArray.HexString (HexString)
import Data.Maybe (fromJust)
import Data.Text.Encoding (decodeUtf8)
import Network.JsonRpc.TinyClient (JsonRpc)
import Network.Polkadot.Account (AccountId,
IdentifyAccount (..),
Ss58Codec (to_ss58check))
import Network.Polkadot.Crypto (MultiPair (..))
import Network.Polkadot.Extrinsic.Era (Era (..))
import Network.Polkadot.Extrinsic.SignedExtension.System
import Network.Polkadot.Extrinsic.SignedExtension.TransactionPayment
import Network.Polkadot.Extrinsic.Unchecked (UncheckedExtrinsic,
sign_extrinsic)
import Network.Polkadot.Primitives (Balance,
Index)
import qualified Network.Polkadot.Primitives as P (MultiAddress,
MultiSignature)
import Network.Polkadot.Rpc.Account (nextIndex)
import Network.Polkadot.Rpc.Author (submitExtrinsic)
import Network.Polkadot.Rpc.Chain (getHeader)
import Network.Polkadot.Rpc.Types (headerNumber,
unBlockNumber)
type Extrinsic a = UncheckedExtrinsic a P.MultiAddress P.MultiSignature SignedExtra
type =
( CheckSpecVersion
, CheckTxVersion
, CheckGenesis
, CheckEra
, CheckNonce
, CheckWeight
, ChargeTransactionPayment
)
new_extra :: (Ss58Codec a, JsonRpc m)
=> a
-> Balance
-> m SignedExtra
a
account_id Balance
tip = do
Index
nonce <- Int -> Index
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Index) -> m Int -> m Index
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> m Int
forall (m :: * -> *). JsonRpc m => Text -> m Int
nextIndex Text
ss58account
Era
era <- m Era
forall (m :: * -> *). JsonRpc m => m Era
mortal_max
SignedExtra -> m SignedExtra
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (SignedExtra -> m SignedExtra) -> SignedExtra -> m SignedExtra
forall a b. (a -> b) -> a -> b
$ Era -> Index -> Balance -> SignedExtra
new_extra' Era
era Index
nonce Balance
tip
where
ss58account :: Text
ss58account = ByteString -> Text
decodeUtf8 (ByteString -> Text) -> ByteString -> Text
forall a b. (a -> b) -> a -> b
$ a -> ByteString
forall a. Ss58Codec a => a -> ByteString
to_ss58check a
account_id
new_extra' :: Era
-> Index
-> Balance
-> SignedExtra
Era
era Index
nonce Balance
tip =
( CheckSpecVersion
CheckSpecVersion
, CheckTxVersion
CheckTxVersion
, CheckGenesis
CheckGenesis
, Era -> CheckEra
CheckEra Era
era
, Compact Index -> CheckNonce
CheckNonce (Index -> Compact Index
forall a. a -> Compact a
Compact Index
nonce)
, CheckWeight
CheckWeight
, Compact Balance -> ChargeTransactionPayment
ChargeTransactionPayment (Balance -> Compact Balance
forall a. a -> Compact a
Compact Balance
tip)
)
mortal_max :: JsonRpc m => m Era
mortal_max :: forall (m :: * -> *). JsonRpc m => m Era
mortal_max = do
Integer
current <- (BlockNumber -> Integer
unBlockNumber (BlockNumber -> Integer)
-> (Maybe Header -> BlockNumber) -> Maybe Header -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Header -> BlockNumber
headerNumber (Header -> BlockNumber)
-> (Maybe Header -> Header) -> Maybe Header -> BlockNumber
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe Header -> Header
forall a. HasCallStack => Maybe a -> a
fromJust) (Maybe Header -> Integer) -> m (Maybe Header) -> m Integer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe HexString -> m (Maybe Header)
forall (m :: * -> *).
JsonRpc m =>
Maybe HexString -> m (Maybe Header)
getHeader Maybe HexString
forall a. Maybe a
Nothing
Era -> m Era
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Era -> m Era) -> Era -> m Era
forall a b. (a -> b) -> a -> b
$ Index -> Index -> Era
MortalEra Index
2048 (Index -> Era) -> Index -> Era
forall a b. (a -> b) -> a -> b
$ Integer -> Index
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer
current Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
1)
sign_and_send :: ( MultiPair pair
, IdentifyAccount (MultiSigner pair)
, Ss58Codec (AccountId (MultiSigner pair))
, Encode (MultiAddress pair)
, Encode (MultiSignature pair)
, Encode call
, JsonRpc m
)
=> pair
-> call
-> Balance
-> m HexString
sign_and_send :: forall pair call (m :: * -> *).
(MultiPair pair, IdentifyAccount (MultiSigner pair),
Ss58Codec (AccountId (MultiSigner pair)),
Encode (MultiAddress pair), Encode (MultiSignature pair),
Encode call, JsonRpc m) =>
pair -> call -> Balance -> m HexString
sign_and_send pair
pair call
call Balance
tip = do
SignedExtra
extra <- AccountId (MultiSigner pair) -> Balance -> m SignedExtra
forall a (m :: * -> *).
(Ss58Codec a, JsonRpc m) =>
a -> Balance -> m SignedExtra
new_extra AccountId (MultiSigner pair)
account_id Balance
tip
UncheckedExtrinsic
call (MultiAddress pair) (MultiSignature pair) SignedExtra
xt <- pair
-> call
-> SignedExtra
-> m (UncheckedExtrinsic
call (MultiAddress pair) (MultiSignature pair) SignedExtra)
forall a c e (m :: * -> *).
(MultiPair a, Encode c, SignedExtension e, JsonRpc m) =>
a
-> c
-> e
-> m (UncheckedExtrinsic c (MultiAddress a) (MultiSignature a) e)
sign_extrinsic pair
pair call
call SignedExtra
extra
HexString -> m HexString
forall (m :: * -> *). JsonRpc m => HexString -> m HexString
submitExtrinsic (UncheckedExtrinsic
call (MultiAddress pair) (MultiSignature pair) SignedExtra
-> HexString
forall a ba. (Encode a, ByteArray ba) => a -> ba
encode UncheckedExtrinsic
call (MultiAddress pair) (MultiSignature pair) SignedExtra
xt)
where
account_id :: AccountId (MultiSigner pair)
account_id = MultiSigner pair -> AccountId (MultiSigner pair)
forall a. IdentifyAccount a => a -> AccountId a
into_account (pair -> MultiSigner pair
forall a. MultiPair a => a -> MultiSigner a
multi_signer pair
pair)