Ethereum accounts¶
Note
Ethereum whitepaper mention two types of accounts: smart contract and external owned account (EOA). But EOA only can send transaction to network. In this page EOA managing and generalized transaction sending is described.
hs-web3 support a few kinds of EOA described in table below.
Type Description Default typically first of node accounts list, should be unlocked Personal available via personal_*
JSON-RPC, password requiredPrivateKey derived from secp256k1 private key, use JSON-RPC sendRawTransaction
All of them has an instance for Account typeclass.
class MonadTrans t => Account a t | t -> a where
-- | Run computation with given account credentials
withAccount :: JsonRpc m => a -> t m b -> m b
-- | Send transaction to contract, like a 'write' command
send :: (JsonRpc m, Method args) => args -> t m TxReceipt
-- | Call constant method of contract, like a 'read' command
call :: (JsonRpc m, Method args, AbiGet result) => args -> t m result
The Account
is a multi-parameter typeclass that define most important EOA actions.
Account managing¶
The first parameter of Account
typeclass is an account internal params presended as independent data type.
-- | Unlockable node managed account params
data Personal = Personal
{ personalAddress :: !Address
, personalPassphrase :: !Passphrase
} deriving (Eq, Show)
In this example Personal
data contains of two params: personal account address and password. For using account credentials Account
typeclass provide special function withAccount
.
-- | Run computation with given account credentials
withAccount :: JsonRpc m => a -> t m b -> m b
withAccount
function takes two arguments: account initialization parameters (some credentials like a password or private key) and computation to run it in given account context. Finally it returns JsonRpc
computation that can be runned using any web3 provider.
runWeb3 $ do
-- Run with default account context
withAccount () $ ...
-- Run with personal account context
withAccount (Personal "0x..." "password") $ ...
Transaction sending¶
The second parameter of Account
typeclass is transaction parametrization monad. This monad do one thing - prepare transaction parameters before call.
Note
Transaction sending diagram by layer looks like provider -> account -> transaction
, provider at low level, account at middle layer and transaction former at high level.
withParam
is a special function, it behaviour is very similar to withStateT
function. It used to set parameters of transaction locally and revert params after out of scope.
withParam :: Account p (AccountT p)
=> (CallParam p -> CallParam p)
-> AccountT p m a
-> AccountT p m a
The first argument of withParam
function is state transition function, second - the computation to run in context of changed state. CallParam
helps to parametrize transaction sending, lenses is very useful for this purpose.
runWeb3 $
withAccount () $
withParam (to .~ alice) $
...
Where lens to
is used for setting transaction recipient address. All transaction parametrization lenses presended in table below.
Note
By default transaction gas limit estimated according to transaction input but it also can be set manually.
Finally for sending transactions Account
typeclass provide two functions:
-- | Send transaction to contract, like a 'write' command
send :: (JsonRpc m, Method args) => args -> t m TxReceipt
-- | Call constant method of contract, like a 'read' command
call :: (JsonRpc m, Method args, AbiGet result) => args -> t m result
Note
Functions above can be run in account context only and transaction parameters should be set before.
Safe transactions¶
Default behaviour of send
function is send transaction and waiting for transaction receipt. It does mean that transaction is already in blockchain when execution flow get back. But finalization in Ethereum is probabilistic. For this reason waiting for some count of confirmation is a good practics for safe transaction sending.
Note
Vitalik Buterin blog post describe how much confirmation is required for high probability of transaction finality. For using this value import safeConfirmations
from Network.Ethereum.Account.Safe
module.
Module Network.Ethereum.Account.Safe
implements function safeSend
. It very similar to send
but take count of transaction confirmation as first argument.
send = safeSend 0