{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE RecordWildCards            #-}

-- |
-- Module      :  Network.Ethereum.Account.Internal
-- Copyright   :  Aleksandr Krupenkin 2016-2024
-- License     :  Apache-2.0
--
-- Maintainer  :  mail@akru.me
-- Stability   :  experimental
-- Portability :  unportable
--
-- Internal types and functions of 'Account' module.
--

module Network.Ethereum.Account.Internal where

import           Control.Concurrent             (threadDelay)
import           Control.Monad.IO.Class         (liftIO)
import           Control.Monad.State.Strict     (MonadState (..), StateT (..),
                                                 withStateT)
import           Control.Monad.Trans            (MonadTrans (..))
import           Data.Default                   (Default (..))
import           Data.Either                    (fromRight)
import           Data.Maybe                     (fromMaybe)
import           Lens.Micro                     (Lens', lens)

import           Data.ByteArray.HexString       (HexString)
import           Data.Solidity.Prim             (Address)
import           Network.Ethereum.Account.Class (Account)
import qualified Network.Ethereum.Api.Eth       as Eth (getTransactionReceipt)
import           Network.Ethereum.Api.Types     (Call (..),
                                                 DefaultBlock (Latest),
                                                 TxReceipt (receiptTransactionHash))
import           Network.Ethereum.Unit          (Unit (..))
import           Network.JsonRpc.TinyClient     (JsonRpc)

-- | Account is needed to send transactions to blockchain

-- | Transaction parametrization data type
data CallParam p = CallParam
    { forall p. CallParam p -> Maybe Address
_to       :: Maybe Address
    -- ^ Transaction recepient
    , forall p. CallParam p -> Integer
_value    :: Integer
    -- ^ Transaction value
    , forall p. CallParam p -> Maybe Integer
_gasLimit :: Maybe Integer
    -- ^ Transaction gas limit
    , forall p. CallParam p -> Maybe Integer
_gasPrice :: Maybe Integer
    -- ^ Transaction gas price
    , forall p. CallParam p -> DefaultBlock
_block    :: DefaultBlock
    -- ^ Call block number
    , forall p. CallParam p -> p
_account  :: p
    -- ^ Account params to sign transaction
    , forall p. CallParam p -> Maybe Int
_timeout  :: Maybe Int
    -- ^ Transaction timeout in microseconds
    } deriving CallParam p -> CallParam p -> Bool
(CallParam p -> CallParam p -> Bool)
-> (CallParam p -> CallParam p -> Bool) -> Eq (CallParam p)
forall p. Eq p => CallParam p -> CallParam p -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall p. Eq p => CallParam p -> CallParam p -> Bool
== :: CallParam p -> CallParam p -> Bool
$c/= :: forall p. Eq p => CallParam p -> CallParam p -> Bool
/= :: CallParam p -> CallParam p -> Bool
Eq

-- | Transaction recipient lens
to :: Lens' (CallParam p) Address
to :: forall p (f :: * -> *).
Functor f =>
(Address -> f Address) -> CallParam p -> f (CallParam p)
to = (CallParam p -> Address)
-> (CallParam p -> Address -> CallParam p)
-> forall {f :: * -> *}.
   Functor f =>
   (Address -> f Address) -> CallParam p -> f (CallParam p)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens (Address -> Maybe Address -> Address
forall a. a -> Maybe a -> a
fromMaybe Address
forall a. Default a => a
def (Maybe Address -> Address)
-> (CallParam p -> Maybe Address) -> CallParam p -> Address
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CallParam p -> Maybe Address
forall p. CallParam p -> Maybe Address
_to) ((CallParam p -> Address -> CallParam p)
 -> forall {f :: * -> *}.
    Functor f =>
    (Address -> f Address) -> CallParam p -> f (CallParam p))
-> (CallParam p -> Address -> CallParam p)
-> forall {f :: * -> *}.
   Functor f =>
   (Address -> f Address) -> CallParam p -> f (CallParam p)
forall a b. (a -> b) -> a -> b
$ \CallParam p
a Address
b -> CallParam p
a { _to = Just b }

-- | Transaction value lens
value :: Unit value => Lens' (CallParam p) value
value :: forall value p. Unit value => Lens' (CallParam p) value
value = (CallParam p -> value)
-> (CallParam p -> value -> CallParam p)
-> forall {f :: * -> *}.
   Functor f =>
   (value -> f value) -> CallParam p -> f (CallParam p)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens (Integer -> value
forall b. Integral b => b -> value
forall a b. (Unit a, Integral b) => b -> a
fromWei (Integer -> value)
-> (CallParam p -> Integer) -> CallParam p -> value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CallParam p -> Integer
forall p. CallParam p -> Integer
_value) ((CallParam p -> value -> CallParam p)
 -> forall {f :: * -> *}.
    Functor f =>
    (value -> f value) -> CallParam p -> f (CallParam p))
-> (CallParam p -> value -> CallParam p)
-> forall {f :: * -> *}.
   Functor f =>
   (value -> f value) -> CallParam p -> f (CallParam p)
forall a b. (a -> b) -> a -> b
$ \CallParam p
a value
b -> CallParam p
a { _value = toWei b }

-- | Transaction gas limit lens
gasLimit :: Lens' (CallParam p) Integer
gasLimit :: forall p (f :: * -> *).
Functor f =>
(Integer -> f Integer) -> CallParam p -> f (CallParam p)
gasLimit = (CallParam p -> Integer)
-> (CallParam p -> Integer -> CallParam p)
-> forall {f :: * -> *}.
   Functor f =>
   (Integer -> f Integer) -> CallParam p -> f (CallParam p)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens (Integer -> Maybe Integer -> Integer
forall a. a -> Maybe a -> a
fromMaybe Integer
forall a. Default a => a
def (Maybe Integer -> Integer)
-> (CallParam p -> Maybe Integer) -> CallParam p -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CallParam p -> Maybe Integer
forall p. CallParam p -> Maybe Integer
_gasLimit) ((CallParam p -> Integer -> CallParam p)
 -> forall {f :: * -> *}.
    Functor f =>
    (Integer -> f Integer) -> CallParam p -> f (CallParam p))
-> (CallParam p -> Integer -> CallParam p)
-> forall {f :: * -> *}.
   Functor f =>
   (Integer -> f Integer) -> CallParam p -> f (CallParam p)
forall a b. (a -> b) -> a -> b
$ \CallParam p
a Integer
b -> CallParam p
a { _gasLimit = Just b }

-- | Transaction gas price lens
gasPrice :: Unit gasprice => Lens' (CallParam p) gasprice
gasPrice :: forall value p. Unit value => Lens' (CallParam p) value
gasPrice = (CallParam p -> gasprice)
-> (CallParam p -> gasprice -> CallParam p)
-> forall {f :: * -> *}.
   Functor f =>
   (gasprice -> f gasprice) -> CallParam p -> f (CallParam p)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens (Integer -> gasprice
forall b. Integral b => b -> gasprice
forall a b. (Unit a, Integral b) => b -> a
fromWei (Integer -> gasprice)
-> (CallParam p -> Integer) -> CallParam p -> gasprice
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Maybe Integer -> Integer
forall a. a -> Maybe a -> a
fromMaybe Integer
forall a. Default a => a
def (Maybe Integer -> Integer)
-> (CallParam p -> Maybe Integer) -> CallParam p -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CallParam p -> Maybe Integer
forall p. CallParam p -> Maybe Integer
_gasPrice) ((CallParam p -> gasprice -> CallParam p)
 -> forall {f :: * -> *}.
    Functor f =>
    (gasprice -> f gasprice) -> CallParam p -> f (CallParam p))
-> (CallParam p -> gasprice -> CallParam p)
-> forall {f :: * -> *}.
   Functor f =>
   (gasprice -> f gasprice) -> CallParam p -> f (CallParam p)
forall a b. (a -> b) -> a -> b
$ \CallParam p
a gasprice
b -> CallParam p
a { _gasPrice = Just (toWei b) }

-- | Call execution block lens
block :: Lens' (CallParam p) DefaultBlock
block :: forall p (f :: * -> *).
Functor f =>
(DefaultBlock -> f DefaultBlock) -> CallParam p -> f (CallParam p)
block = (CallParam p -> DefaultBlock)
-> (CallParam p -> DefaultBlock -> CallParam p)
-> forall {f :: * -> *}.
   Functor f =>
   (DefaultBlock -> f DefaultBlock) -> CallParam p -> f (CallParam p)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens CallParam p -> DefaultBlock
forall p. CallParam p -> DefaultBlock
_block ((CallParam p -> DefaultBlock -> CallParam p)
 -> forall {f :: * -> *}.
    Functor f =>
    (DefaultBlock -> f DefaultBlock) -> CallParam p -> f (CallParam p))
-> (CallParam p -> DefaultBlock -> CallParam p)
-> forall {f :: * -> *}.
   Functor f =>
   (DefaultBlock -> f DefaultBlock) -> CallParam p -> f (CallParam p)
forall a b. (a -> b) -> a -> b
$ \CallParam p
a DefaultBlock
b -> CallParam p
a { _block = b }

-- | EOA params lens
account :: Lens' (CallParam p) p
account :: forall p (f :: * -> *).
Functor f =>
(p -> f p) -> CallParam p -> f (CallParam p)
account = (CallParam p -> p)
-> (CallParam p -> p -> CallParam p)
-> forall {f :: * -> *}.
   Functor f =>
   (p -> f p) -> CallParam p -> f (CallParam p)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens CallParam p -> p
forall p. CallParam p -> p
_account ((CallParam p -> p -> CallParam p)
 -> forall {f :: * -> *}.
    Functor f =>
    (p -> f p) -> CallParam p -> f (CallParam p))
-> (CallParam p -> p -> CallParam p)
-> forall {f :: * -> *}.
   Functor f =>
   (p -> f p) -> CallParam p -> f (CallParam p)
forall a b. (a -> b) -> a -> b
$ \CallParam p
a p
b -> CallParam p
a { _account = b }

-- | Transaction timeout lens
timeout :: Lens' (CallParam p) (Maybe Int)
timeout :: forall p (f :: * -> *).
Functor f =>
(Maybe Int -> f (Maybe Int)) -> CallParam p -> f (CallParam p)
timeout = (CallParam p -> Maybe Int)
-> (CallParam p -> Maybe Int -> CallParam p)
-> forall {f :: * -> *}.
   Functor f =>
   (Maybe Int -> f (Maybe Int)) -> CallParam p -> f (CallParam p)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens CallParam p -> Maybe Int
forall p. CallParam p -> Maybe Int
_timeout ((CallParam p -> Maybe Int -> CallParam p)
 -> forall {f :: * -> *}.
    Functor f =>
    (Maybe Int -> f (Maybe Int)) -> CallParam p -> f (CallParam p))
-> (CallParam p -> Maybe Int -> CallParam p)
-> forall {f :: * -> *}.
   Functor f =>
   (Maybe Int -> f (Maybe Int)) -> CallParam p -> f (CallParam p)
forall a b. (a -> b) -> a -> b
$ \CallParam p
a Maybe Int
b -> CallParam p
a { _timeout = b }

-- | Monad transformer for sending parametrized transactions from account
newtype AccountT p m a = AccountT
    { forall p (m :: * -> *) a.
AccountT p m a -> StateT (CallParam p) m a
runAccountT :: StateT (CallParam p) m a }
  deriving ((forall a b. (a -> b) -> AccountT p m a -> AccountT p m b)
-> (forall a b. a -> AccountT p m b -> AccountT p m a)
-> Functor (AccountT p m)
forall a b. a -> AccountT p m b -> AccountT p m a
forall a b. (a -> b) -> AccountT p m a -> AccountT p m b
forall p (m :: * -> *) a b.
Functor m =>
a -> AccountT p m b -> AccountT p m a
forall p (m :: * -> *) a b.
Functor m =>
(a -> b) -> AccountT p m a -> AccountT p m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall p (m :: * -> *) a b.
Functor m =>
(a -> b) -> AccountT p m a -> AccountT p m b
fmap :: forall a b. (a -> b) -> AccountT p m a -> AccountT p m b
$c<$ :: forall p (m :: * -> *) a b.
Functor m =>
a -> AccountT p m b -> AccountT p m a
<$ :: forall a b. a -> AccountT p m b -> AccountT p m a
Functor, Functor (AccountT p m)
Functor (AccountT p m) =>
(forall a. a -> AccountT p m a)
-> (forall a b.
    AccountT p m (a -> b) -> AccountT p m a -> AccountT p m b)
-> (forall a b c.
    (a -> b -> c)
    -> AccountT p m a -> AccountT p m b -> AccountT p m c)
-> (forall a b. AccountT p m a -> AccountT p m b -> AccountT p m b)
-> (forall a b. AccountT p m a -> AccountT p m b -> AccountT p m a)
-> Applicative (AccountT p m)
forall a. a -> AccountT p m a
forall a b. AccountT p m a -> AccountT p m b -> AccountT p m a
forall a b. AccountT p m a -> AccountT p m b -> AccountT p m b
forall a b.
AccountT p m (a -> b) -> AccountT p m a -> AccountT p m b
forall a b c.
(a -> b -> c) -> AccountT p m a -> AccountT p m b -> AccountT p m c
forall p (m :: * -> *). Monad m => Functor (AccountT p m)
forall p (m :: * -> *) a. Monad m => a -> AccountT p m a
forall p (m :: * -> *) a b.
Monad m =>
AccountT p m a -> AccountT p m b -> AccountT p m a
forall p (m :: * -> *) a b.
Monad m =>
AccountT p m a -> AccountT p m b -> AccountT p m b
forall p (m :: * -> *) a b.
Monad m =>
AccountT p m (a -> b) -> AccountT p m a -> AccountT p m b
forall p (m :: * -> *) a b c.
Monad m =>
(a -> b -> c) -> AccountT p m a -> AccountT p m b -> AccountT p m c
forall (f :: * -> *).
Functor f =>
(forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
$cpure :: forall p (m :: * -> *) a. Monad m => a -> AccountT p m a
pure :: forall a. a -> AccountT p m a
$c<*> :: forall p (m :: * -> *) a b.
Monad m =>
AccountT p m (a -> b) -> AccountT p m a -> AccountT p m b
<*> :: forall a b.
AccountT p m (a -> b) -> AccountT p m a -> AccountT p m b
$cliftA2 :: forall p (m :: * -> *) a b c.
Monad m =>
(a -> b -> c) -> AccountT p m a -> AccountT p m b -> AccountT p m c
liftA2 :: forall a b c.
(a -> b -> c) -> AccountT p m a -> AccountT p m b -> AccountT p m c
$c*> :: forall p (m :: * -> *) a b.
Monad m =>
AccountT p m a -> AccountT p m b -> AccountT p m b
*> :: forall a b. AccountT p m a -> AccountT p m b -> AccountT p m b
$c<* :: forall p (m :: * -> *) a b.
Monad m =>
AccountT p m a -> AccountT p m b -> AccountT p m a
<* :: forall a b. AccountT p m a -> AccountT p m b -> AccountT p m a
Applicative, Applicative (AccountT p m)
Applicative (AccountT p m) =>
(forall a b.
 AccountT p m a -> (a -> AccountT p m b) -> AccountT p m b)
-> (forall a b. AccountT p m a -> AccountT p m b -> AccountT p m b)
-> (forall a. a -> AccountT p m a)
-> Monad (AccountT p m)
forall a. a -> AccountT p m a
forall a b. AccountT p m a -> AccountT p m b -> AccountT p m b
forall a b.
AccountT p m a -> (a -> AccountT p m b) -> AccountT p m b
forall p (m :: * -> *). Monad m => Applicative (AccountT p m)
forall p (m :: * -> *) a. Monad m => a -> AccountT p m a
forall p (m :: * -> *) a b.
Monad m =>
AccountT p m a -> AccountT p m b -> AccountT p m b
forall p (m :: * -> *) a b.
Monad m =>
AccountT p m a -> (a -> AccountT p m b) -> AccountT p m b
forall (m :: * -> *).
Applicative m =>
(forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
$c>>= :: forall p (m :: * -> *) a b.
Monad m =>
AccountT p m a -> (a -> AccountT p m b) -> AccountT p m b
>>= :: forall a b.
AccountT p m a -> (a -> AccountT p m b) -> AccountT p m b
$c>> :: forall p (m :: * -> *) a b.
Monad m =>
AccountT p m a -> AccountT p m b -> AccountT p m b
>> :: forall a b. AccountT p m a -> AccountT p m b -> AccountT p m b
$creturn :: forall p (m :: * -> *) a. Monad m => a -> AccountT p m a
return :: forall a. a -> AccountT p m a
Monad, (forall (m :: * -> *). Monad m => Monad (AccountT p m)) =>
(forall (m :: * -> *) a. Monad m => m a -> AccountT p m a)
-> MonadTrans (AccountT p)
forall p (m :: * -> *). Monad m => Monad (AccountT p m)
forall p (m :: * -> *) a. Monad m => m a -> AccountT p m a
forall (m :: * -> *). Monad m => Monad (AccountT p m)
forall (m :: * -> *) a. Monad m => m a -> AccountT p m a
forall (t :: (* -> *) -> * -> *).
(forall (m :: * -> *). Monad m => Monad (t m)) =>
(forall (m :: * -> *) a. Monad m => m a -> t m a) -> MonadTrans t
$clift :: forall p (m :: * -> *) a. Monad m => m a -> AccountT p m a
lift :: forall (m :: * -> *) a. Monad m => m a -> AccountT p m a
MonadTrans)

instance Monad m => MonadState (CallParam p) (AccountT p m) where
    get :: AccountT p m (CallParam p)
get = StateT (CallParam p) m (CallParam p) -> AccountT p m (CallParam p)
forall p (m :: * -> *) a.
StateT (CallParam p) m a -> AccountT p m a
AccountT StateT (CallParam p) m (CallParam p)
forall s (m :: * -> *). MonadState s m => m s
get
    put :: CallParam p -> AccountT p m ()
put = StateT (CallParam p) m () -> AccountT p m ()
forall p (m :: * -> *) a.
StateT (CallParam p) m a -> AccountT p m a
AccountT (StateT (CallParam p) m () -> AccountT p m ())
-> (CallParam p -> StateT (CallParam p) m ())
-> CallParam p
-> AccountT p m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CallParam p -> StateT (CallParam p) m ()
forall s (m :: * -> *). MonadState s m => s -> m ()
put

-- | @withParam@ is very similar to @withStateT@ function, it's used
-- to set parameters of transaction locally and revert params after out of scope.
--
--  @
--  withAccount () $
--    withParam (to .~ tokenAddress) $
--      transfer alice 42
--  @
withParam :: Account p (AccountT p)
          => (CallParam p -> CallParam p)
          -> AccountT p m a
          -> AccountT p m a
{-# INLINE withParam #-}
withParam :: forall p (m :: * -> *) a.
Account p (AccountT p) =>
(CallParam p -> CallParam p) -> AccountT p m a -> AccountT p m a
withParam CallParam p -> CallParam p
f AccountT p m a
m = StateT (CallParam p) m a -> AccountT p m a
forall p (m :: * -> *) a.
StateT (CallParam p) m a -> AccountT p m a
AccountT (StateT (CallParam p) m a -> AccountT p m a)
-> StateT (CallParam p) m a -> AccountT p m a
forall a b. (a -> b) -> a -> b
$ (CallParam p -> CallParam p)
-> StateT (CallParam p) m a -> StateT (CallParam p) m a
forall s (m :: * -> *) a. (s -> s) -> StateT s m a -> StateT s m a
withStateT CallParam p -> CallParam p
f (StateT (CallParam p) m a -> StateT (CallParam p) m a)
-> StateT (CallParam p) m a -> StateT (CallParam p) m a
forall a b. (a -> b) -> a -> b
$ AccountT p m a -> StateT (CallParam p) m a
forall p (m :: * -> *) a.
AccountT p m a -> StateT (CallParam p) m a
runAccountT AccountT p m a
m

defaultCallParam :: a -> CallParam a
{-# INLINE defaultCallParam #-}
defaultCallParam :: forall a. a -> CallParam a
defaultCallParam a
acc = Maybe Address
-> Integer
-> Maybe Integer
-> Maybe Integer
-> DefaultBlock
-> a
-> Maybe Int
-> CallParam a
forall p.
Maybe Address
-> Integer
-> Maybe Integer
-> Maybe Integer
-> DefaultBlock
-> p
-> Maybe Int
-> CallParam p
CallParam Maybe Address
forall a. Default a => a
def Integer
0 Maybe Integer
forall a. Maybe a
Nothing Maybe Integer
forall a. Maybe a
Nothing DefaultBlock
Latest a
acc Maybe Int
forall a. Maybe a
Nothing

getCall :: MonadState (CallParam p) m => m Call
getCall :: forall p (m :: * -> *). MonadState (CallParam p) m => m Call
getCall = do
    CallParam{p
Integer
Maybe Int
Maybe Integer
Maybe Address
DefaultBlock
_to :: forall p. CallParam p -> Maybe Address
_value :: forall p. CallParam p -> Integer
_gasLimit :: forall p. CallParam p -> Maybe Integer
_gasPrice :: forall p. CallParam p -> Maybe Integer
_block :: forall p. CallParam p -> DefaultBlock
_account :: forall p. CallParam p -> p
_timeout :: forall p. CallParam p -> Maybe Int
_to :: Maybe Address
_value :: Integer
_gasLimit :: Maybe Integer
_gasPrice :: Maybe Integer
_block :: DefaultBlock
_account :: p
_timeout :: Maybe Int
..} <- m (CallParam p)
forall s (m :: * -> *). MonadState s m => m s
get
    Call -> m Call
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Call -> m Call) -> Call -> m Call
forall a b. (a -> b) -> a -> b
$ Call
forall a. Default a => a
def { callTo       = _to
                 , callValue    = Just $ fromInteger _value
                 , callGas      = fromInteger <$> _gasLimit
                 , callGasPrice = fromInteger <$> _gasPrice
                 }

getReceipt :: JsonRpc m => Maybe Int -> HexString -> m (Either HexString TxReceipt)
getReceipt :: forall (m :: * -> *).
JsonRpc m =>
Maybe Int -> HexString -> m (Either HexString TxReceipt)
getReceipt Maybe Int
mbtimeout HexString
tx = do
    Maybe TxReceipt
mbreceipt <- HexString -> m (Maybe TxReceipt)
forall (m :: * -> *). JsonRpc m => HexString -> m (Maybe TxReceipt)
Eth.getTransactionReceipt HexString
tx
    case Maybe TxReceipt
mbreceipt of
        Just TxReceipt
receipt -> Either HexString TxReceipt -> m (Either HexString TxReceipt)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either HexString TxReceipt -> m (Either HexString TxReceipt))
-> Either HexString TxReceipt -> m (Either HexString TxReceipt)
forall a b. (a -> b) -> a -> b
$ TxReceipt -> Either HexString TxReceipt
forall a b. b -> Either a b
Right TxReceipt
receipt
        Maybe TxReceipt
Nothing -> case Maybe Int
mbtimeout of
            Just Int
us
                | Int
us Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 -> Maybe Int -> m (Either HexString TxReceipt)
forall {m :: * -> *}.
JsonRpc m =>
Maybe Int -> m (Either HexString TxReceipt)
retry (Maybe Int -> m (Either HexString TxReceipt))
-> Maybe Int -> m (Either HexString TxReceipt)
forall a b. (a -> b) -> a -> b
$ Int -> Maybe Int
forall a. a -> Maybe a
Just (Int -> Maybe Int) -> Int -> Maybe Int
forall a b. (a -> b) -> a -> b
$ Int
us Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
100000
                | Bool
otherwise -> Either HexString TxReceipt -> m (Either HexString TxReceipt)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either HexString TxReceipt -> m (Either HexString TxReceipt))
-> Either HexString TxReceipt -> m (Either HexString TxReceipt)
forall a b. (a -> b) -> a -> b
$ HexString -> Either HexString TxReceipt
forall a b. a -> Either a b
Left HexString
tx
            Maybe Int
Nothing -> Maybe Int -> m (Either HexString TxReceipt)
forall {m :: * -> *}.
JsonRpc m =>
Maybe Int -> m (Either HexString TxReceipt)
retry Maybe Int
forall a. Maybe a
Nothing
    where
        retry :: Maybe Int -> m (Either HexString TxReceipt)
retry Maybe Int
mbtimeout' = do
            IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ Int -> IO ()
threadDelay Int
100000
            Maybe Int -> HexString -> m (Either HexString TxReceipt)
forall (m :: * -> *).
JsonRpc m =>
Maybe Int -> HexString -> m (Either HexString TxReceipt)
getReceipt Maybe Int
mbtimeout' HexString
tx

getReceipt' :: JsonRpc m => HexString -> m TxReceipt
getReceipt' :: forall (m :: * -> *). JsonRpc m => HexString -> m TxReceipt
getReceipt' = (Either HexString TxReceipt -> TxReceipt)
-> m (Either HexString TxReceipt) -> m TxReceipt
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (TxReceipt -> Either HexString TxReceipt -> TxReceipt
forall b a. b -> Either a b -> b
fromRight TxReceipt
forall a. HasCallStack => a
undefined) (m (Either HexString TxReceipt) -> m TxReceipt)
-> (HexString -> m (Either HexString TxReceipt))
-> HexString
-> m TxReceipt
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe Int -> HexString -> m (Either HexString TxReceipt)
forall (m :: * -> *).
JsonRpc m =>
Maybe Int -> HexString -> m (Either HexString TxReceipt)
getReceipt Maybe Int
forall a. Maybe a
Nothing

updateReceipt :: JsonRpc m => TxReceipt -> m TxReceipt
{-# INLINE updateReceipt #-}
-- No timeout, because we update the receipt of an already processed transaction.
updateReceipt :: forall (m :: * -> *). JsonRpc m => TxReceipt -> m TxReceipt
updateReceipt = HexString -> m TxReceipt
forall (m :: * -> *). JsonRpc m => HexString -> m TxReceipt
getReceipt' (HexString -> m TxReceipt)
-> (TxReceipt -> HexString) -> TxReceipt -> m TxReceipt
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxReceipt -> HexString
receiptTransactionHash