{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecordWildCards #-}

-- |
-- Copyright: © 2018-2020 IOHK
-- License: Apache-2.0
--
-- Database / Persistence layer for the wallet backend. This is where we define
-- the interface allowing us to store and fetch various data on our wallets.

module Cardano.Wallet.DB
    ( -- * Interface
      DBLayer (..)
    , DBFactory (..)
    , cleanDB

      -- * Errors
    , ErrBadFormat(..)
    , ErrWalletAlreadyExists(..)
    , ErrNoSuchTransaction (..)
    , ErrRemoveTx (..)
    , ErrPutLocalTxSubmission (..)
    ) where

import Prelude

import Cardano.Address.Derivation
    ( XPrv )
import Cardano.Wallet.DB.WalletState
    ( DeltaMap, DeltaWalletState, ErrNoSuchWallet (..) )
import Cardano.Wallet.Primitive.AddressDerivation
    ( Depth (..) )
import Cardano.Wallet.Primitive.Model
    ( Wallet )
import Cardano.Wallet.Primitive.Passphrase
    ( PassphraseHash )
import Cardano.Wallet.Primitive.Types
    ( ChainPoint
    , DelegationCertificate
    , GenesisParameters
    , Range (..)
    , Slot
    , SlotNo (..)
    , SortOrder (..)
    , WalletId
    , WalletMetadata
    )
import Cardano.Wallet.Primitive.Types.Coin
    ( Coin )
import Cardano.Wallet.Primitive.Types.Hash
    ( Hash )
import Cardano.Wallet.Primitive.Types.Tx
    ( LocalTxSubmissionStatus
    , SealedTx
    , TransactionInfo
    , Tx (..)
    , TxMeta
    , TxStatus
    )
import Control.Monad.IO.Class
    ( MonadIO )
import Control.Monad.Trans.Except
    ( ExceptT, runExceptT )
import Data.DBVar
    ( DBVar )
import Data.Quantity
    ( Quantity (..) )
import Data.Word
    ( Word32 )
import UnliftIO.Exception
    ( Exception )

-- | Instantiate database layers at will
data DBFactory m s k = DBFactory
    { DBFactory m s k
-> forall a. WalletId -> (DBLayer m s k -> IO a) -> IO a
withDatabase :: forall a. WalletId -> (DBLayer m s k -> IO a) -> IO a
        -- ^ Creates a new or use an existing database, maintaining an open
        -- connection so long as necessary

    , DBFactory m s k -> WalletId -> IO ()
removeDatabase :: WalletId -> IO ()
        -- ^ Erase any trace of the database

    , DBFactory m s k -> IO [WalletId]
listDatabases :: IO [WalletId]
        -- ^ List existing wallet database found on disk.
    }

-- | A Database interface for storing various things in a DB. In practice,
-- we'll need some extra constraints on the wallet state that allows us to
-- serialize and unserialize it (e.g. @forall s. (Serialize s) => ...@)
--
-- NOTE:
--
-- We can't use record accessors on the DBLayer as it carries an existential
-- within its constructor. We are forced to pattern-match on the `DBLayer`
-- record type in order to be able to use its methods in any context. With
-- NamedFieldPuns, or RecordWildCards, this can be quite easy:
--
-- @
-- myFunction DBLayer{..} = do
--     ...
--
-- myOtherFunction DBLayer{atomically,initializeWallet} = do
--     ...
-- @
--
-- Alternatively, in some other context where the database may not be a function
-- argument but come from a different source, it is possible to simply rely on
-- 'Data.Function.(&)' to easily pattern match on it:
--
-- @
-- myFunction arg0 arg1 = db & \DBLayer{..} -> do
--     ...
--   where
--     db = ...
-- @
--
-- Note that it isn't possible to simply use a @where@ clause or a @let@ binding
-- here as the semantic for those are slightly different: we really need a
-- pattern match here!
data DBLayer m s k = forall stm. (MonadIO stm, MonadFail stm) => DBLayer
    { ()
initializeWallet
        :: WalletId
        -> Wallet s
        -> WalletMetadata
        -> [(Tx, TxMeta)]
        -> GenesisParameters
        -> ExceptT ErrWalletAlreadyExists stm ()
        -- ^ Initialize a database entry for a given wallet. 'putCheckpoint',
        -- 'putWalletMeta', 'putTxHistory' or 'putProtocolParameters' will
        -- actually all fail if they are called _first_ on a wallet.

    , ()
removeWallet
        :: WalletId
        -> ExceptT ErrNoSuchWallet stm ()
        -- ^ Remove a given wallet and all its associated data (checkpoints,
        -- metadata, tx history ...)

    , ()
listWallets
        :: stm [WalletId]
        -- ^ Get the list of all known wallets in the DB, possibly empty.

    , ()
walletsDB
        :: DBVar stm (DeltaMap WalletId (DeltaWalletState s))
        -- ^ 'DBVar' containing the 'WalletState' of each wallet in the database.
        -- Currently contains all 'Checkpoints' of the 'UTxO' and the
        -- 'Discoveries', as well as the 'Prologue' of the address discovery state.
        --
        -- Intended to replace 'putCheckpoint' and 'readCheckpoint' in the short-term,
        -- and all other functions in the long-term.

    , ()
putCheckpoint
        :: WalletId
        -> Wallet s
        -> ExceptT ErrNoSuchWallet stm ()
        -- ^ Replace the current checkpoint for a given wallet. We do not handle
        -- rollbacks yet, and therefore only stores the latest available
        -- checkpoint.
        --
        -- If the wallet doesn't exist, this operation returns an error.

    , ()
readCheckpoint
        :: WalletId
        -> stm (Maybe (Wallet s))
        -- ^ Fetch the most recent checkpoint of a given wallet.
        --
        -- Return 'Nothing' if there's no such wallet.

    , ()
listCheckpoints
        :: WalletId
        -> stm [ChainPoint]
        -- ^ List all known checkpoint tips, ordered by slot ids from the oldest
        -- to the newest.

    , ()
putWalletMeta
        :: WalletId
        -> WalletMetadata
        -> ExceptT ErrNoSuchWallet stm ()
        -- ^ Replace an existing wallet metadata with the given one.
        --
        -- If the wallet doesn't exist, this operation returns an error

    , ()
readWalletMeta
        :: WalletId
        -> stm (Maybe WalletMetadata)
        -- ^ Fetch a wallet metadata, if they exist.
        --
        -- Return 'Nothing' if there's no such wallet.

    , ()
isStakeKeyRegistered
        :: WalletId
        -> ExceptT ErrNoSuchWallet stm Bool

    , ()
putDelegationCertificate
        :: WalletId
        -> DelegationCertificate
        -> SlotNo
        -> ExceptT ErrNoSuchWallet stm ()
        -- ^ Binds a stake pool id to a wallet. This will have an influence on
        -- the wallet metadata: the last known certificate will indicate to
        -- which pool a wallet is currently delegating.
        --
        -- This is done separately from 'putWalletMeta' because certificate
        -- declarations are:
        --
        -- 1. Stored on-chain.
        -- 2. Affected by rollbacks (or said differently, tied to a 'SlotNo').

    , ()
putDelegationRewardBalance
        :: WalletId
        -> Coin
        -> ExceptT ErrNoSuchWallet stm ()
        -- ^ Store the latest known reward account balance.
        --
        -- This is separate from checkpoints because the data corresponds to the
        -- node tip.
        -- This is separate from putWalletMeta because it's not meta data

    , ()
readDelegationRewardBalance
        :: WalletId
        -> stm Coin
        -- ^ Get the reward account balance.
        --
        -- Returns zero if the wallet isn't found or if wallet hasn't delegated
        -- stake.

    , ()
putTxHistory
        :: WalletId
        -> [(Tx, TxMeta)]
        -> ExceptT ErrNoSuchWallet stm ()
        -- ^ Augments the transaction history for a known wallet.
        --
        -- If an entry for a particular transaction already exists it is not
        -- altered nor merged (just ignored).
        --
        -- If the wallet doesn't exist, this operation returns an error.

    , ()
readTxHistory
        :: WalletId
        -> Maybe Coin
        -> SortOrder
        -> Range SlotNo
        -> Maybe TxStatus
        -> stm [TransactionInfo]
        -- ^ Fetch the current transaction history of a known wallet, ordered by
        -- descending slot number.
        --
        -- Returns an empty list if the wallet isn't found.

    , ()
getTx
        :: WalletId
        -> Hash "Tx"
        -> ExceptT ErrNoSuchWallet stm (Maybe TransactionInfo)
        -- ^ Fetch the latest transaction by id, returns Nothing when the
        -- transaction isn't found.
        --
        -- If the wallet doesn't exist, this operation returns an error.

    , ()
putLocalTxSubmission
        :: WalletId
        -> Hash "Tx"
        -> SealedTx
        -> SlotNo
        -> ExceptT ErrPutLocalTxSubmission stm ()
        -- ^ Add or update a transaction in the local submission pool with the
        -- most recent submission slot.

    , ()
readLocalTxSubmissionPending
        :: WalletId
        -> stm [LocalTxSubmissionStatus SealedTx]
        -- ^ List all transactions from the local submission pool which are
        -- still pending as of the latest checkpoint of the given wallet. The
        -- slot numbers for first submission and most recent submission are
        -- included.

    , ()
updatePendingTxForExpiry
        :: WalletId
        -> SlotNo
        -> ExceptT ErrNoSuchWallet stm ()
        -- ^ Removes any expired transactions from the pending set and marks
        -- their status as expired.

    , ()
removePendingOrExpiredTx
        :: WalletId
        -> Hash "Tx"
        -> ExceptT ErrRemoveTx stm ()
        -- ^ Manually remove a pending transaction.

    , ()
putPrivateKey
        :: WalletId
        -> (k 'RootK XPrv, PassphraseHash)
        -> ExceptT ErrNoSuchWallet stm ()
        -- ^ Store or replace a private key for a given wallet. Note that wallet
        -- _could_ be stored and manipulated without any private key associated
        -- to it. A private key is only seldomly required for very specific
        -- operations (like transaction signing).

    , ()
readPrivateKey
        :: WalletId
        -> stm (Maybe (k 'RootK XPrv, PassphraseHash))
        -- ^ Read a previously stored private key and its associated passphrase
        -- hash.

    , ()
readGenesisParameters
        :: WalletId
        -> stm (Maybe GenesisParameters)
        -- ^ Read the *Byron* genesis parameters.

    , ()
rollbackTo
        :: WalletId
        -> Slot
        -> ExceptT ErrNoSuchWallet stm ChainPoint
        -- ^ Drops all checkpoints and transaction data which
        -- have appeared after the given 'ChainPoint'.
        --
        -- Returns the actual 'ChainPoint' to which the database has rolled back.
        -- Its slot is guaranteed to be earlier than (or identical to) the given
        -- point of rollback but can't be guaranteed to be exactly the same
        -- because the database may only keep sparse checkpoints.

    , ()
prune
        :: WalletId
        -> Quantity "block" Word32
        -> ExceptT ErrNoSuchWallet stm ()
        -- ^ Prune database entities and remove entities that can be discarded.
        --
        -- The second argument represents the stability window, or said
        -- length of the deepest rollback.

    , ()
atomically
        :: forall a. stm a -> m a
        -- ^ Execute operations of the database in isolation and atomically.
    }

-- | Can't read the database file because it's in a bad format
-- (corrupted, too old, …)
data ErrBadFormat
    = ErrBadFormatAddressPrologue
    | ErrBadFormatCheckpoints
    deriving (ErrBadFormat -> ErrBadFormat -> Bool
(ErrBadFormat -> ErrBadFormat -> Bool)
-> (ErrBadFormat -> ErrBadFormat -> Bool) -> Eq ErrBadFormat
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ErrBadFormat -> ErrBadFormat -> Bool
$c/= :: ErrBadFormat -> ErrBadFormat -> Bool
== :: ErrBadFormat -> ErrBadFormat -> Bool
$c== :: ErrBadFormat -> ErrBadFormat -> Bool
Eq,Int -> ErrBadFormat -> ShowS
[ErrBadFormat] -> ShowS
ErrBadFormat -> String
(Int -> ErrBadFormat -> ShowS)
-> (ErrBadFormat -> String)
-> ([ErrBadFormat] -> ShowS)
-> Show ErrBadFormat
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ErrBadFormat] -> ShowS
$cshowList :: [ErrBadFormat] -> ShowS
show :: ErrBadFormat -> String
$cshow :: ErrBadFormat -> String
showsPrec :: Int -> ErrBadFormat -> ShowS
$cshowsPrec :: Int -> ErrBadFormat -> ShowS
Show)

instance Exception ErrBadFormat

-- | Can't add a transaction to the local tx submission pool.
data ErrPutLocalTxSubmission
    = ErrPutLocalTxSubmissionNoSuchWallet ErrNoSuchWallet
    | ErrPutLocalTxSubmissionNoSuchTransaction ErrNoSuchTransaction
    deriving (ErrPutLocalTxSubmission -> ErrPutLocalTxSubmission -> Bool
(ErrPutLocalTxSubmission -> ErrPutLocalTxSubmission -> Bool)
-> (ErrPutLocalTxSubmission -> ErrPutLocalTxSubmission -> Bool)
-> Eq ErrPutLocalTxSubmission
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ErrPutLocalTxSubmission -> ErrPutLocalTxSubmission -> Bool
$c/= :: ErrPutLocalTxSubmission -> ErrPutLocalTxSubmission -> Bool
== :: ErrPutLocalTxSubmission -> ErrPutLocalTxSubmission -> Bool
$c== :: ErrPutLocalTxSubmission -> ErrPutLocalTxSubmission -> Bool
Eq, Int -> ErrPutLocalTxSubmission -> ShowS
[ErrPutLocalTxSubmission] -> ShowS
ErrPutLocalTxSubmission -> String
(Int -> ErrPutLocalTxSubmission -> ShowS)
-> (ErrPutLocalTxSubmission -> String)
-> ([ErrPutLocalTxSubmission] -> ShowS)
-> Show ErrPutLocalTxSubmission
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ErrPutLocalTxSubmission] -> ShowS
$cshowList :: [ErrPutLocalTxSubmission] -> ShowS
show :: ErrPutLocalTxSubmission -> String
$cshow :: ErrPutLocalTxSubmission -> String
showsPrec :: Int -> ErrPutLocalTxSubmission -> ShowS
$cshowsPrec :: Int -> ErrPutLocalTxSubmission -> ShowS
Show)

-- | Can't remove pending or expired transaction.
data ErrRemoveTx
    = ErrRemoveTxNoSuchWallet ErrNoSuchWallet
    | ErrRemoveTxNoSuchTransaction ErrNoSuchTransaction
    | ErrRemoveTxAlreadyInLedger (Hash "Tx")
    deriving (ErrRemoveTx -> ErrRemoveTx -> Bool
(ErrRemoveTx -> ErrRemoveTx -> Bool)
-> (ErrRemoveTx -> ErrRemoveTx -> Bool) -> Eq ErrRemoveTx
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ErrRemoveTx -> ErrRemoveTx -> Bool
$c/= :: ErrRemoveTx -> ErrRemoveTx -> Bool
== :: ErrRemoveTx -> ErrRemoveTx -> Bool
$c== :: ErrRemoveTx -> ErrRemoveTx -> Bool
Eq, Int -> ErrRemoveTx -> ShowS
[ErrRemoveTx] -> ShowS
ErrRemoveTx -> String
(Int -> ErrRemoveTx -> ShowS)
-> (ErrRemoveTx -> String)
-> ([ErrRemoveTx] -> ShowS)
-> Show ErrRemoveTx
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ErrRemoveTx] -> ShowS
$cshowList :: [ErrRemoveTx] -> ShowS
show :: ErrRemoveTx -> String
$cshow :: ErrRemoveTx -> String
showsPrec :: Int -> ErrRemoveTx -> ShowS
$cshowsPrec :: Int -> ErrRemoveTx -> ShowS
Show)

-- | Indicates that the specified transaction hash is not found in the
-- transaction history of the given wallet.
data ErrNoSuchTransaction
    = ErrNoSuchTransaction WalletId (Hash "Tx")
    deriving (ErrNoSuchTransaction -> ErrNoSuchTransaction -> Bool
(ErrNoSuchTransaction -> ErrNoSuchTransaction -> Bool)
-> (ErrNoSuchTransaction -> ErrNoSuchTransaction -> Bool)
-> Eq ErrNoSuchTransaction
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ErrNoSuchTransaction -> ErrNoSuchTransaction -> Bool
$c/= :: ErrNoSuchTransaction -> ErrNoSuchTransaction -> Bool
== :: ErrNoSuchTransaction -> ErrNoSuchTransaction -> Bool
$c== :: ErrNoSuchTransaction -> ErrNoSuchTransaction -> Bool
Eq, Int -> ErrNoSuchTransaction -> ShowS
[ErrNoSuchTransaction] -> ShowS
ErrNoSuchTransaction -> String
(Int -> ErrNoSuchTransaction -> ShowS)
-> (ErrNoSuchTransaction -> String)
-> ([ErrNoSuchTransaction] -> ShowS)
-> Show ErrNoSuchTransaction
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ErrNoSuchTransaction] -> ShowS
$cshowList :: [ErrNoSuchTransaction] -> ShowS
show :: ErrNoSuchTransaction -> String
$cshow :: ErrNoSuchTransaction -> String
showsPrec :: Int -> ErrNoSuchTransaction -> ShowS
$cshowsPrec :: Int -> ErrNoSuchTransaction -> ShowS
Show)

-- | Forbidden operation was executed on an already existing wallet
newtype ErrWalletAlreadyExists
    = ErrWalletAlreadyExists WalletId -- Wallet already exists in db
    deriving (ErrWalletAlreadyExists -> ErrWalletAlreadyExists -> Bool
(ErrWalletAlreadyExists -> ErrWalletAlreadyExists -> Bool)
-> (ErrWalletAlreadyExists -> ErrWalletAlreadyExists -> Bool)
-> Eq ErrWalletAlreadyExists
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ErrWalletAlreadyExists -> ErrWalletAlreadyExists -> Bool
$c/= :: ErrWalletAlreadyExists -> ErrWalletAlreadyExists -> Bool
== :: ErrWalletAlreadyExists -> ErrWalletAlreadyExists -> Bool
$c== :: ErrWalletAlreadyExists -> ErrWalletAlreadyExists -> Bool
Eq, Int -> ErrWalletAlreadyExists -> ShowS
[ErrWalletAlreadyExists] -> ShowS
ErrWalletAlreadyExists -> String
(Int -> ErrWalletAlreadyExists -> ShowS)
-> (ErrWalletAlreadyExists -> String)
-> ([ErrWalletAlreadyExists] -> ShowS)
-> Show ErrWalletAlreadyExists
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ErrWalletAlreadyExists] -> ShowS
$cshowList :: [ErrWalletAlreadyExists] -> ShowS
show :: ErrWalletAlreadyExists -> String
$cshow :: ErrWalletAlreadyExists -> String
showsPrec :: Int -> ErrWalletAlreadyExists -> ShowS
$cshowsPrec :: Int -> ErrWalletAlreadyExists -> ShowS
Show)

-- | Clean a database by removing all wallets.
cleanDB :: DBLayer m s k -> m ()
cleanDB :: DBLayer m s k -> m ()
cleanDB DBLayer{stm [WalletId]
DBVar stm (DeltaMap WalletId (DeltaWalletState s))
WalletId -> stm [LocalTxSubmissionStatus SealedTx]
WalletId -> stm [ChainPoint]
WalletId -> stm (Maybe (k 'RootK XPrv, PassphraseHash))
WalletId -> stm (Maybe GenesisParameters)
WalletId -> stm (Maybe WalletMetadata)
WalletId -> stm (Maybe (Wallet s))
WalletId -> stm Coin
WalletId -> ExceptT ErrNoSuchWallet stm Bool
WalletId -> ExceptT ErrNoSuchWallet stm ()
WalletId -> [(Tx, TxMeta)] -> ExceptT ErrNoSuchWallet stm ()
WalletId
-> Maybe Coin
-> SortOrder
-> Range SlotNo
-> Maybe TxStatus
-> stm [TransactionInfo]
WalletId
-> (k 'RootK XPrv, PassphraseHash)
-> ExceptT ErrNoSuchWallet stm ()
WalletId -> SlotNo -> ExceptT ErrNoSuchWallet stm ()
WalletId -> Slot -> ExceptT ErrNoSuchWallet stm ChainPoint
WalletId
-> Hash "Tx" -> ExceptT ErrNoSuchWallet stm (Maybe TransactionInfo)
WalletId -> Hash "Tx" -> ExceptT ErrRemoveTx stm ()
WalletId
-> Hash "Tx"
-> SealedTx
-> SlotNo
-> ExceptT ErrPutLocalTxSubmission stm ()
WalletId
-> Quantity "block" Word32 -> ExceptT ErrNoSuchWallet stm ()
WalletId -> Coin -> ExceptT ErrNoSuchWallet stm ()
WalletId
-> DelegationCertificate
-> SlotNo
-> ExceptT ErrNoSuchWallet stm ()
WalletId -> WalletMetadata -> ExceptT ErrNoSuchWallet stm ()
WalletId -> Wallet s -> ExceptT ErrNoSuchWallet stm ()
WalletId
-> Wallet s
-> WalletMetadata
-> [(Tx, TxMeta)]
-> GenesisParameters
-> ExceptT ErrWalletAlreadyExists stm ()
forall a. stm a -> m a
atomically :: forall a. stm a -> m a
prune :: WalletId
-> Quantity "block" Word32 -> ExceptT ErrNoSuchWallet stm ()
rollbackTo :: WalletId -> Slot -> ExceptT ErrNoSuchWallet stm ChainPoint
readGenesisParameters :: WalletId -> stm (Maybe GenesisParameters)
readPrivateKey :: WalletId -> stm (Maybe (k 'RootK XPrv, PassphraseHash))
putPrivateKey :: WalletId
-> (k 'RootK XPrv, PassphraseHash)
-> ExceptT ErrNoSuchWallet stm ()
removePendingOrExpiredTx :: WalletId -> Hash "Tx" -> ExceptT ErrRemoveTx stm ()
updatePendingTxForExpiry :: WalletId -> SlotNo -> ExceptT ErrNoSuchWallet stm ()
readLocalTxSubmissionPending :: WalletId -> stm [LocalTxSubmissionStatus SealedTx]
putLocalTxSubmission :: WalletId
-> Hash "Tx"
-> SealedTx
-> SlotNo
-> ExceptT ErrPutLocalTxSubmission stm ()
getTx :: WalletId
-> Hash "Tx" -> ExceptT ErrNoSuchWallet stm (Maybe TransactionInfo)
readTxHistory :: WalletId
-> Maybe Coin
-> SortOrder
-> Range SlotNo
-> Maybe TxStatus
-> stm [TransactionInfo]
putTxHistory :: WalletId -> [(Tx, TxMeta)] -> ExceptT ErrNoSuchWallet stm ()
readDelegationRewardBalance :: WalletId -> stm Coin
putDelegationRewardBalance :: WalletId -> Coin -> ExceptT ErrNoSuchWallet stm ()
putDelegationCertificate :: WalletId
-> DelegationCertificate
-> SlotNo
-> ExceptT ErrNoSuchWallet stm ()
isStakeKeyRegistered :: WalletId -> ExceptT ErrNoSuchWallet stm Bool
readWalletMeta :: WalletId -> stm (Maybe WalletMetadata)
putWalletMeta :: WalletId -> WalletMetadata -> ExceptT ErrNoSuchWallet stm ()
listCheckpoints :: WalletId -> stm [ChainPoint]
readCheckpoint :: WalletId -> stm (Maybe (Wallet s))
putCheckpoint :: WalletId -> Wallet s -> ExceptT ErrNoSuchWallet stm ()
walletsDB :: DBVar stm (DeltaMap WalletId (DeltaWalletState s))
listWallets :: stm [WalletId]
removeWallet :: WalletId -> ExceptT ErrNoSuchWallet stm ()
initializeWallet :: WalletId
-> Wallet s
-> WalletMetadata
-> [(Tx, TxMeta)]
-> GenesisParameters
-> ExceptT ErrWalletAlreadyExists stm ()
atomically :: ()
prune :: ()
rollbackTo :: ()
readGenesisParameters :: ()
readPrivateKey :: ()
putPrivateKey :: ()
removePendingOrExpiredTx :: ()
updatePendingTxForExpiry :: ()
readLocalTxSubmissionPending :: ()
putLocalTxSubmission :: ()
getTx :: ()
readTxHistory :: ()
putTxHistory :: ()
readDelegationRewardBalance :: ()
putDelegationRewardBalance :: ()
putDelegationCertificate :: ()
isStakeKeyRegistered :: ()
readWalletMeta :: ()
putWalletMeta :: ()
listCheckpoints :: ()
readCheckpoint :: ()
putCheckpoint :: ()
walletsDB :: ()
listWallets :: ()
removeWallet :: ()
initializeWallet :: ()
..} = stm () -> m ()
forall a. stm a -> m a
atomically (stm () -> m ()) -> stm () -> m ()
forall a b. (a -> b) -> a -> b
$
    stm [WalletId]
listWallets stm [WalletId] -> ([WalletId] -> stm ()) -> stm ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (WalletId -> stm (Either ErrNoSuchWallet ()))
-> [WalletId] -> stm ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (ExceptT ErrNoSuchWallet stm () -> stm (Either ErrNoSuchWallet ())
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT (ExceptT ErrNoSuchWallet stm () -> stm (Either ErrNoSuchWallet ()))
-> (WalletId -> ExceptT ErrNoSuchWallet stm ())
-> WalletId
-> stm (Either ErrNoSuchWallet ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WalletId -> ExceptT ErrNoSuchWallet stm ()
removeWallet)