{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE NoFieldSelectors #-}

module Haskoin.Store.Database.Reader
  ( -- * RocksDB Database Access
    DatabaseReader (..),
    DatabaseReaderT,
    DataMetrics,
    withDB,
    createDataMetrics,
    withDatabaseReader,
    addrTxCF,
    addrOutCF,
    txCF,
    unspentCF,
    blockCF,
    heightCF,
    balanceCF,
  )
where

import Conduit
  ( ConduitT,
    dropWhileC,
    lift,
    mapC,
    runConduit,
    sinkList,
    (.|),
  )
import Control.Monad.Except (runExceptT, throwError)
import Control.Monad.Reader (MonadReader, ReaderT, asks, runReaderT)
import Control.Monad.Trans.Maybe (MaybeT (..), runMaybeT)
import Data.Bits ((.&.))
import Data.ByteString qualified as BS
import Data.Default (def)
import Data.IntMap.Strict qualified as IntMap
import Data.List (sortOn)
import Data.Maybe (fromMaybe)
import Data.Ord (Down (..))
import Data.Serialize (encode)
import Data.Word (Word32)
import Database.RocksDB
  ( ColumnFamily,
    Config (..),
    DB (..),
    Iterator,
    withDBCF,
    withIterCF,
  )
import Database.RocksDB.Query
  ( insert,
    matching,
    matchingAsListCF,
    matchingSkip,
    retrieve,
    retrieveCF,
  )
import Haskoin
import Haskoin.Store.Common
import Haskoin.Store.Data
import Haskoin.Store.Database.Types
import System.Metrics.StatsD
import UnliftIO (MonadIO, MonadUnliftIO, bracket_, liftIO)

type DatabaseReaderT = ReaderT DatabaseReader

data DatabaseReader = DatabaseReader
  { DatabaseReader -> DB
db :: !DB,
    DatabaseReader -> Word32
maxGap :: !Word32,
    DatabaseReader -> Word32
initGap :: !Word32,
    DatabaseReader -> Network
net :: !Network,
    DatabaseReader -> Maybe DataMetrics
metrics :: !(Maybe DataMetrics),
    DatabaseReader -> Ctx
ctx :: !Ctx
  }

data DataMetrics = DataMetrics
  { DataMetrics -> StatCounter
dataBestCount :: !StatCounter,
    DataMetrics -> StatCounter
dataBlockCount :: !StatCounter,
    DataMetrics -> StatCounter
dataTxCount :: !StatCounter,
    DataMetrics -> StatCounter
dataMempoolCount :: !StatCounter,
    DataMetrics -> StatCounter
dataBalanceCount :: !StatCounter,
    DataMetrics -> StatCounter
dataUnspentCount :: !StatCounter,
    DataMetrics -> StatCounter
dataAddrTxCount :: !StatCounter,
    DataMetrics -> StatCounter
dataXPubBals :: !StatCounter,
    DataMetrics -> StatCounter
dataXPubUnspents :: !StatCounter,
    DataMetrics -> StatCounter
dataXPubTxs :: !StatCounter,
    DataMetrics -> StatCounter
dataXPubTxCount :: !StatCounter,
    DataMetrics -> StatGauge
dataIters :: !StatGauge
  }

createDataMetrics :: (MonadIO m) => Stats -> m DataMetrics
createDataMetrics :: forall (m :: * -> *). MonadIO m => Stats -> m DataMetrics
createDataMetrics Stats
s = do
  StatCounter
dataBestCount <- Stats -> Key -> Int -> m StatCounter
forall (m :: * -> *).
MonadIO m =>
Stats -> Key -> Int -> m StatCounter
newStatCounter Stats
s Key
"db.best_block" Int
n
  StatCounter
dataBlockCount <- Stats -> Key -> Int -> m StatCounter
forall (m :: * -> *).
MonadIO m =>
Stats -> Key -> Int -> m StatCounter
newStatCounter Stats
s Key
"db.blocks" Int
n
  StatCounter
dataTxCount <- Stats -> Key -> Int -> m StatCounter
forall (m :: * -> *).
MonadIO m =>
Stats -> Key -> Int -> m StatCounter
newStatCounter Stats
s Key
"db.txs" Int
n
  StatCounter
dataMempoolCount <- Stats -> Key -> Int -> m StatCounter
forall (m :: * -> *).
MonadIO m =>
Stats -> Key -> Int -> m StatCounter
newStatCounter Stats
s Key
"db.mempool" Int
n
  StatCounter
dataBalanceCount <- Stats -> Key -> Int -> m StatCounter
forall (m :: * -> *).
MonadIO m =>
Stats -> Key -> Int -> m StatCounter
newStatCounter Stats
s Key
"db.balances" Int
n
  StatCounter
dataUnspentCount <- Stats -> Key -> Int -> m StatCounter
forall (m :: * -> *).
MonadIO m =>
Stats -> Key -> Int -> m StatCounter
newStatCounter Stats
s Key
"db.unspents" Int
n
  StatCounter
dataAddrTxCount <- Stats -> Key -> Int -> m StatCounter
forall (m :: * -> *).
MonadIO m =>
Stats -> Key -> Int -> m StatCounter
newStatCounter Stats
s Key
"db.address_txs" Int
n
  StatCounter
dataXPubBals <- Stats -> Key -> Int -> m StatCounter
forall (m :: * -> *).
MonadIO m =>
Stats -> Key -> Int -> m StatCounter
newStatCounter Stats
s Key
"db.xpub_balances" Int
n
  StatCounter
dataXPubUnspents <- Stats -> Key -> Int -> m StatCounter
forall (m :: * -> *).
MonadIO m =>
Stats -> Key -> Int -> m StatCounter
newStatCounter Stats
s Key
"db.xpub_unspents" Int
n
  StatCounter
dataXPubTxs <- Stats -> Key -> Int -> m StatCounter
forall (m :: * -> *).
MonadIO m =>
Stats -> Key -> Int -> m StatCounter
newStatCounter Stats
s Key
"db.xpub_txs" Int
n
  StatCounter
dataXPubTxCount <- Stats -> Key -> Int -> m StatCounter
forall (m :: * -> *).
MonadIO m =>
Stats -> Key -> Int -> m StatCounter
newStatCounter Stats
s Key
"db.xpub_tx_count" Int
n
  StatGauge
dataIters <- Stats -> Key -> Int -> m StatGauge
forall (m :: * -> *).
MonadIO m =>
Stats -> Key -> Int -> m StatGauge
newStatGauge Stats
s Key
"db.iterators" Int
0
  DataMetrics -> m DataMetrics
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return DataMetrics {StatGauge
StatCounter
$sel:dataBestCount:DataMetrics :: StatCounter
$sel:dataBlockCount:DataMetrics :: StatCounter
$sel:dataTxCount:DataMetrics :: StatCounter
$sel:dataMempoolCount:DataMetrics :: StatCounter
$sel:dataBalanceCount:DataMetrics :: StatCounter
$sel:dataUnspentCount:DataMetrics :: StatCounter
$sel:dataAddrTxCount:DataMetrics :: StatCounter
$sel:dataXPubBals:DataMetrics :: StatCounter
$sel:dataXPubUnspents:DataMetrics :: StatCounter
$sel:dataXPubTxs:DataMetrics :: StatCounter
$sel:dataXPubTxCount:DataMetrics :: StatCounter
$sel:dataIters:DataMetrics :: StatGauge
dataBestCount :: StatCounter
dataBlockCount :: StatCounter
dataTxCount :: StatCounter
dataMempoolCount :: StatCounter
dataBalanceCount :: StatCounter
dataUnspentCount :: StatCounter
dataAddrTxCount :: StatCounter
dataXPubBals :: StatCounter
dataXPubUnspents :: StatCounter
dataXPubTxs :: StatCounter
dataXPubTxCount :: StatCounter
dataIters :: StatGauge
..}
  where
    n :: Int
n = Int
10

withMetrics :: (MonadReader DatabaseReader m) => (DataMetrics -> m a) -> m ()
withMetrics :: forall (m :: * -> *) a.
MonadReader DatabaseReader m =>
(DataMetrics -> m a) -> m ()
withMetrics DataMetrics -> m a
go = (DatabaseReader -> Maybe DataMetrics) -> m (Maybe DataMetrics)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (.metrics) m (Maybe DataMetrics) -> (Maybe DataMetrics -> m ()) -> m ()
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (DataMetrics -> m a) -> Maybe DataMetrics -> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ DataMetrics -> m a
go

dataVersion :: Word32
dataVersion :: Word32
dataVersion = Word32
18

withDB :: DatabaseReader -> DatabaseReaderT m a -> m a
withDB :: forall (m :: * -> *) a.
DatabaseReader -> DatabaseReaderT m a -> m a
withDB = (DatabaseReaderT m a -> DatabaseReader -> m a)
-> DatabaseReader -> DatabaseReaderT m a -> m a
forall a b c. (a -> b -> c) -> b -> a -> c
flip DatabaseReaderT m a -> DatabaseReader -> m a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT

withDatabaseReader ::
  (MonadUnliftIO m) =>
  Network ->
  Ctx ->
  Word32 ->
  Word32 ->
  FilePath ->
  Maybe DataMetrics ->
  DatabaseReaderT m a ->
  m a
withDatabaseReader :: forall (m :: * -> *) a.
MonadUnliftIO m =>
Network
-> Ctx
-> Word32
-> Word32
-> Key
-> Maybe DataMetrics
-> DatabaseReaderT m a
-> m a
withDatabaseReader Network
net Ctx
ctx Word32
igap Word32
gap Key
dir Maybe DataMetrics
stats DatabaseReaderT m a
f =
  Key -> Config -> [(Key, Config)] -> (DB -> m a) -> m a
forall (m :: * -> *) a.
MonadUnliftIO m =>
Key -> Config -> [(Key, Config)] -> (DB -> m a) -> m a
withDBCF Key
dir Config
cfg [(Key, Config)]
columnFamilyConfig ((DB -> m a) -> m a) -> (DB -> m a) -> m a
forall a b. (a -> b) -> a -> b
$ \DB
db -> do
    let bdb :: DatabaseReader
bdb =
          DatabaseReader
            { $sel:db:DatabaseReader :: DB
db = DB
db,
              $sel:maxGap:DatabaseReader :: Word32
maxGap = Word32
gap,
              $sel:net:DatabaseReader :: Network
net = Network
net,
              $sel:initGap:DatabaseReader :: Word32
initGap = Word32
igap,
              $sel:metrics:DatabaseReader :: Maybe DataMetrics
metrics = Maybe DataMetrics
stats,
              $sel:ctx:DatabaseReader :: Ctx
ctx = Ctx
ctx
            }
    DatabaseReader -> m ()
forall (m :: * -> *). MonadIO m => DatabaseReader -> m ()
initRocksDB DatabaseReader
bdb
    DatabaseReaderT m a -> DatabaseReader -> m a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT DatabaseReaderT m a
f DatabaseReader
bdb
  where
    cfg :: Config
cfg = Config
forall a. Default a => a
def {createIfMissing = True}

columnFamilyConfig :: [(String, Config)]
columnFamilyConfig :: [(Key, Config)]
columnFamilyConfig =
  [ (Key
"addr-tx", Config
forall a. Default a => a
def {prefixLength = Just 22, bloomFilter = True}),
    (Key
"addr-out", Config
forall a. Default a => a
def {prefixLength = Just 22, bloomFilter = True}),
    (Key
"tx", Config
forall a. Default a => a
def {prefixLength = Just 33, bloomFilter = True}),
    (Key
"spender", Config
forall a. Default a => a
def {prefixLength = Just 33, bloomFilter = True}), -- unused
    (Key
"unspent", Config
forall a. Default a => a
def {prefixLength = Just 37, bloomFilter = True}),
    (Key
"block", Config
forall a. Default a => a
def {prefixLength = Just 33, bloomFilter = True}),
    (Key
"height", Config
forall a. Default a => a
def {prefixLength = Nothing, bloomFilter = True}),
    (Key
"balance", Config
forall a. Default a => a
def {prefixLength = Just 22, bloomFilter = True})
  ]

addrTxCF :: DB -> ColumnFamily
addrTxCF :: DB -> ColumnFamily
addrTxCF = [ColumnFamily] -> ColumnFamily
forall a. HasCallStack => [a] -> a
head ([ColumnFamily] -> ColumnFamily)
-> (DB -> [ColumnFamily]) -> DB -> ColumnFamily
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DB -> [ColumnFamily]
columnFamilies

addrOutCF :: DB -> ColumnFamily
addrOutCF :: DB -> ColumnFamily
addrOutCF DB
db = DB -> [ColumnFamily]
columnFamilies DB
db [ColumnFamily] -> Int -> ColumnFamily
forall a. HasCallStack => [a] -> Int -> a
!! Int
1

txCF :: DB -> ColumnFamily
txCF :: DB -> ColumnFamily
txCF DB
db = DB -> [ColumnFamily]
columnFamilies DB
db [ColumnFamily] -> Int -> ColumnFamily
forall a. HasCallStack => [a] -> Int -> a
!! Int
2

unspentCF :: DB -> ColumnFamily
unspentCF :: DB -> ColumnFamily
unspentCF DB
db = DB -> [ColumnFamily]
columnFamilies DB
db [ColumnFamily] -> Int -> ColumnFamily
forall a. HasCallStack => [a] -> Int -> a
!! Int
4

blockCF :: DB -> ColumnFamily
blockCF :: DB -> ColumnFamily
blockCF DB
db = DB -> [ColumnFamily]
columnFamilies DB
db [ColumnFamily] -> Int -> ColumnFamily
forall a. HasCallStack => [a] -> Int -> a
!! Int
5

heightCF :: DB -> ColumnFamily
heightCF :: DB -> ColumnFamily
heightCF DB
db = DB -> [ColumnFamily]
columnFamilies DB
db [ColumnFamily] -> Int -> ColumnFamily
forall a. HasCallStack => [a] -> Int -> a
!! Int
6

balanceCF :: DB -> ColumnFamily
balanceCF :: DB -> ColumnFamily
balanceCF DB
db = DB -> [ColumnFamily]
columnFamilies DB
db [ColumnFamily] -> Int -> ColumnFamily
forall a. HasCallStack => [a] -> Int -> a
!! Int
7

initRocksDB :: (MonadIO m) => DatabaseReader -> m ()
initRocksDB :: forall (m :: * -> *). MonadIO m => DatabaseReader -> m ()
initRocksDB DatabaseReader {$sel:db:DatabaseReader :: DatabaseReader -> DB
db = DB
db} = do
  Either Key ()
e <-
    ExceptT Key m () -> m (Either Key ())
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT (ExceptT Key m () -> m (Either Key ()))
-> ExceptT Key m () -> m (Either Key ())
forall a b. (a -> b) -> a -> b
$
      DB -> VersionKey -> ExceptT Key m (Maybe Word32)
forall (m :: * -> *) key value.
(MonadIO m, KeyValue key value, Serialize key, Serialize value) =>
DB -> key -> m (Maybe value)
retrieve DB
db VersionKey
VersionKey ExceptT Key m (Maybe Word32)
-> (Maybe Word32 -> ExceptT Key m ()) -> ExceptT Key m ()
forall a b.
ExceptT Key m a -> (a -> ExceptT Key m b) -> ExceptT Key m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
        Just Word32
v
          | Word32
v Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
== Word32
dataVersion -> () -> ExceptT Key m ()
forall a. a -> ExceptT Key m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
          | Bool
otherwise -> Key -> ExceptT Key m ()
forall a. Key -> ExceptT Key m a
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError Key
"Incorrect RocksDB database version"
        Maybe Word32
Nothing -> DB -> ExceptT Key m ()
forall (m :: * -> *). MonadIO m => DB -> m ()
setInitRocksDB DB
db
  case Either Key ()
e of
    Left Key
s -> Key -> m ()
forall a. HasCallStack => Key -> a
error Key
s
    Right () -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()

setInitRocksDB :: (MonadIO m) => DB -> m ()
setInitRocksDB :: forall (m :: * -> *). MonadIO m => DB -> m ()
setInitRocksDB DB
db = DB -> VersionKey -> Word32 -> m ()
forall (m :: * -> *) key value.
(MonadIO m, KeyValue key value, Serialize key, Serialize value) =>
DB -> key -> value -> m ()
insert DB
db VersionKey
VersionKey Word32
dataVersion

addressConduit ::
  (MonadUnliftIO m) =>
  Address ->
  Maybe Start ->
  Iterator ->
  ConduitT i TxRef (DatabaseReaderT m) ()
addressConduit :: forall (m :: * -> *) i.
MonadUnliftIO m =>
Address
-> Maybe Start
-> Iterator
-> ConduitT i TxRef (DatabaseReaderT m) ()
addressConduit Address
a Maybe Start
s Iterator
it =
  ConduitT i (AddrTxKey, ()) (DatabaseReaderT m) ()
forall {i}. ConduitT i (AddrTxKey, ()) (DatabaseReaderT m) ()
x ConduitT i (AddrTxKey, ()) (DatabaseReaderT m) ()
-> ConduitT (AddrTxKey, ()) TxRef (DatabaseReaderT m) ()
-> ConduitT i TxRef (DatabaseReaderT m) ()
forall (m :: * -> *) a b c r.
Monad m =>
ConduitT a b m () -> ConduitT b c m r -> ConduitT a c m r
.| ((AddrTxKey, ()) -> TxRef)
-> ConduitT (AddrTxKey, ()) TxRef (DatabaseReaderT m) ()
forall (m :: * -> *) a b. Monad m => (a -> b) -> ConduitT a b m ()
mapC ((AddrTxKey -> () -> TxRef) -> (AddrTxKey, ()) -> TxRef
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry AddrTxKey -> () -> TxRef
f)
  where
    f :: AddrTxKey -> () -> TxRef
f (AddrTxKey Address
_ TxRef
t) () = TxRef
t
    f AddrTxKey
_ ()
_ = TxRef
forall a. HasCallStack => a
undefined
    x :: ConduitT i (AddrTxKey, ()) (DatabaseReaderT m) ()
x = case Maybe Start
s of
      Maybe Start
Nothing ->
        Iterator
-> AddrTxKey -> ConduitT i (AddrTxKey, ()) (DatabaseReaderT m) ()
forall (m :: * -> *) key value i.
(MonadIO m, KeyValue key value, Serialize key, Serialize value) =>
Iterator -> key -> ConduitT i (key, value) m ()
matching Iterator
it (Address -> AddrTxKey
AddrTxKeyA Address
a)
      Just (AtBlock Word32
bh) ->
        Iterator
-> AddrTxKey
-> AddrTxKey
-> ConduitT i (AddrTxKey, ()) (DatabaseReaderT m) ()
forall (m :: * -> *) key value i.
(MonadIO m, KeyValue key value, Serialize key, Serialize value) =>
Iterator -> key -> key -> ConduitT i (key, value) m ()
matchingSkip
          Iterator
it
          (Address -> AddrTxKey
AddrTxKeyA Address
a)
          (Address -> BlockRef -> AddrTxKey
AddrTxKeyB Address
a (Word32 -> Word32 -> BlockRef
BlockRef Word32
bh Word32
forall a. Bounded a => a
maxBound))
      Just (AtTx TxHash
txh) ->
        DatabaseReaderT m (Maybe TxData)
-> ConduitT i (AddrTxKey, ()) (DatabaseReaderT m) (Maybe TxData)
forall (m :: * -> *) a.
Monad m =>
m a -> ConduitT i (AddrTxKey, ()) m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (TxHash -> DatabaseReaderT m (Maybe TxData)
forall (m :: * -> *). StoreReadBase m => TxHash -> m (Maybe TxData)
getTxData TxHash
txh) ConduitT i (AddrTxKey, ()) (DatabaseReaderT m) (Maybe TxData)
-> (Maybe TxData
    -> ConduitT i (AddrTxKey, ()) (DatabaseReaderT m) ())
-> ConduitT i (AddrTxKey, ()) (DatabaseReaderT m) ()
forall a b.
ConduitT i (AddrTxKey, ()) (DatabaseReaderT m) a
-> (a -> ConduitT i (AddrTxKey, ()) (DatabaseReaderT m) b)
-> ConduitT i (AddrTxKey, ()) (DatabaseReaderT m) b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
          Just TxData {$sel:block:TxData :: TxData -> BlockRef
block = b :: BlockRef
b@BlockRef {}} ->
            Iterator
-> AddrTxKey
-> AddrTxKey
-> ConduitT i (AddrTxKey, ()) (DatabaseReaderT m) ()
forall (m :: * -> *) key value i.
(MonadIO m, KeyValue key value, Serialize key, Serialize value) =>
Iterator -> key -> key -> ConduitT i (key, value) m ()
matchingSkip Iterator
it (Address -> AddrTxKey
AddrTxKeyA Address
a) (Address -> BlockRef -> AddrTxKey
AddrTxKeyB Address
a BlockRef
b)
          Just TxData {$sel:block:TxData :: TxData -> BlockRef
block = MemRef {}} ->
            let cond :: AddrTxKey -> Bool
cond (AddrTxKey Address
_ (TxRef MemRef {} TxHash
th)) = TxHash
th TxHash -> TxHash -> Bool
forall a. Eq a => a -> a -> Bool
/= TxHash
txh
                cond (AddrTxKey Address
_ (TxRef BlockRef {} TxHash
_)) = Bool
False
                cond AddrTxKey
_ = Bool
forall a. HasCallStack => a
undefined
             in Iterator
-> AddrTxKey -> ConduitT i (AddrTxKey, ()) (DatabaseReaderT m) ()
forall (m :: * -> *) key value i.
(MonadIO m, KeyValue key value, Serialize key, Serialize value) =>
Iterator -> key -> ConduitT i (key, value) m ()
matching Iterator
it (Address -> AddrTxKey
AddrTxKeyA Address
a)
                  ConduitT i (AddrTxKey, ()) (DatabaseReaderT m) ()
-> ConduitT (AddrTxKey, ()) (AddrTxKey, ()) (DatabaseReaderT m) ()
-> ConduitT i (AddrTxKey, ()) (DatabaseReaderT m) ()
forall (m :: * -> *) a b c r.
Monad m =>
ConduitT a b m () -> ConduitT b c m r -> ConduitT a c m r
.| (((AddrTxKey, ()) -> Bool)
-> ConduitT (AddrTxKey, ()) (AddrTxKey, ()) (DatabaseReaderT m) ()
forall (m :: * -> *) a o.
Monad m =>
(a -> Bool) -> ConduitT a o m ()
dropWhileC (AddrTxKey -> Bool
cond (AddrTxKey -> Bool)
-> ((AddrTxKey, ()) -> AddrTxKey) -> (AddrTxKey, ()) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (AddrTxKey, ()) -> AddrTxKey
forall a b. (a, b) -> a
fst) ConduitT (AddrTxKey, ()) (AddrTxKey, ()) (DatabaseReaderT m) ()
-> ConduitT (AddrTxKey, ()) (AddrTxKey, ()) (DatabaseReaderT m) ()
-> ConduitT (AddrTxKey, ()) (AddrTxKey, ()) (DatabaseReaderT m) ()
forall a b.
ConduitT (AddrTxKey, ()) (AddrTxKey, ()) (DatabaseReaderT m) a
-> ConduitT (AddrTxKey, ()) (AddrTxKey, ()) (DatabaseReaderT m) b
-> ConduitT (AddrTxKey, ()) (AddrTxKey, ()) (DatabaseReaderT m) b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ((AddrTxKey, ()) -> (AddrTxKey, ()))
-> ConduitT (AddrTxKey, ()) (AddrTxKey, ()) (DatabaseReaderT m) ()
forall (m :: * -> *) a b. Monad m => (a -> b) -> ConduitT a b m ()
mapC (AddrTxKey, ()) -> (AddrTxKey, ())
forall a. a -> a
id)
          Maybe TxData
Nothing -> () -> ConduitT i (AddrTxKey, ()) (DatabaseReaderT m) ()
forall a. a -> ConduitT i (AddrTxKey, ()) (DatabaseReaderT m) a
forall (m :: * -> *) a. Monad m => a -> m a
return ()

unspentConduit ::
  (MonadUnliftIO m) =>
  Ctx ->
  Address ->
  Maybe Start ->
  Iterator ->
  ConduitT i Unspent (DatabaseReaderT m) ()
unspentConduit :: forall (m :: * -> *) i.
MonadUnliftIO m =>
Ctx
-> Address
-> Maybe Start
-> Iterator
-> ConduitT i Unspent (DatabaseReaderT m) ()
unspentConduit Ctx
ctx Address
a Maybe Start
s Iterator
it =
  ConduitT i (AddrOutKey, OutVal) (DatabaseReaderT m) ()
forall {i}. ConduitT i (AddrOutKey, OutVal) (DatabaseReaderT m) ()
x ConduitT i (AddrOutKey, OutVal) (DatabaseReaderT m) ()
-> ConduitT (AddrOutKey, OutVal) Unspent (DatabaseReaderT m) ()
-> ConduitT i Unspent (DatabaseReaderT m) ()
forall (m :: * -> *) a b c r.
Monad m =>
ConduitT a b m () -> ConduitT b c m r -> ConduitT a c m r
.| ((AddrOutKey, OutVal) -> Unspent)
-> ConduitT (AddrOutKey, OutVal) Unspent (DatabaseReaderT m) ()
forall (m :: * -> *) a b. Monad m => (a -> b) -> ConduitT a b m ()
mapC ((AddrOutKey -> OutVal -> Unspent)
-> (AddrOutKey, OutVal) -> Unspent
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (Ctx -> AddrOutKey -> OutVal -> Unspent
toUnspent Ctx
ctx))
  where
    x :: ConduitT i (AddrOutKey, OutVal) (DatabaseReaderT m) ()
x = case Maybe Start
s of
      Maybe Start
Nothing ->
        Iterator
-> AddrOutKey
-> ConduitT i (AddrOutKey, OutVal) (DatabaseReaderT m) ()
forall (m :: * -> *) key value i.
(MonadIO m, KeyValue key value, Serialize key, Serialize value) =>
Iterator -> key -> ConduitT i (key, value) m ()
matching Iterator
it (Address -> AddrOutKey
AddrOutKeyA Address
a)
      Just (AtBlock Word32
h) ->
        Iterator
-> AddrOutKey
-> AddrOutKey
-> ConduitT i (AddrOutKey, OutVal) (DatabaseReaderT m) ()
forall (m :: * -> *) key value i.
(MonadIO m, KeyValue key value, Serialize key, Serialize value) =>
Iterator -> key -> key -> ConduitT i (key, value) m ()
matchingSkip
          Iterator
it
          (Address -> AddrOutKey
AddrOutKeyA Address
a)
          (Address -> BlockRef -> AddrOutKey
AddrOutKeyB Address
a (Word32 -> Word32 -> BlockRef
BlockRef Word32
h Word32
forall a. Bounded a => a
maxBound))
      Just (AtTx TxHash
txh) ->
        DatabaseReaderT m (Maybe TxData)
-> ConduitT
     i (AddrOutKey, OutVal) (DatabaseReaderT m) (Maybe TxData)
forall (m :: * -> *) a.
Monad m =>
m a -> ConduitT i (AddrOutKey, OutVal) m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (TxHash -> DatabaseReaderT m (Maybe TxData)
forall (m :: * -> *). StoreReadBase m => TxHash -> m (Maybe TxData)
getTxData TxHash
txh) ConduitT i (AddrOutKey, OutVal) (DatabaseReaderT m) (Maybe TxData)
-> (Maybe TxData
    -> ConduitT i (AddrOutKey, OutVal) (DatabaseReaderT m) ())
-> ConduitT i (AddrOutKey, OutVal) (DatabaseReaderT m) ()
forall a b.
ConduitT i (AddrOutKey, OutVal) (DatabaseReaderT m) a
-> (a -> ConduitT i (AddrOutKey, OutVal) (DatabaseReaderT m) b)
-> ConduitT i (AddrOutKey, OutVal) (DatabaseReaderT m) b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
          Just TxData {$sel:block:TxData :: TxData -> BlockRef
block = b :: BlockRef
b@BlockRef {}} ->
            Iterator
-> AddrOutKey
-> AddrOutKey
-> ConduitT i (AddrOutKey, OutVal) (DatabaseReaderT m) ()
forall (m :: * -> *) key value i.
(MonadIO m, KeyValue key value, Serialize key, Serialize value) =>
Iterator -> key -> key -> ConduitT i (key, value) m ()
matchingSkip Iterator
it (Address -> AddrOutKey
AddrOutKeyA Address
a) (Address -> BlockRef -> AddrOutKey
AddrOutKeyB Address
a BlockRef
b)
          Just TxData {$sel:block:TxData :: TxData -> BlockRef
block = MemRef {}} ->
            let cond :: AddrOutKey -> Bool
cond (AddrOutKey Address
_ MemRef {} OutPoint
p) = OutPoint
p.hash TxHash -> TxHash -> Bool
forall a. Eq a => a -> a -> Bool
/= TxHash
txh
                cond (AddrOutKey Address
_ BlockRef {} OutPoint
_) = Bool
False
                cond AddrOutKey
_ = Bool
forall a. HasCallStack => a
undefined
             in Iterator
-> AddrOutKey
-> ConduitT i (AddrOutKey, OutVal) (DatabaseReaderT m) ()
forall (m :: * -> *) key value i.
(MonadIO m, KeyValue key value, Serialize key, Serialize value) =>
Iterator -> key -> ConduitT i (key, value) m ()
matching Iterator
it (Address -> AddrOutKey
AddrOutKeyA Address
a)
                  ConduitT i (AddrOutKey, OutVal) (DatabaseReaderT m) ()
-> ConduitT
     (AddrOutKey, OutVal) (AddrOutKey, OutVal) (DatabaseReaderT m) ()
-> ConduitT i (AddrOutKey, OutVal) (DatabaseReaderT m) ()
forall (m :: * -> *) a b c r.
Monad m =>
ConduitT a b m () -> ConduitT b c m r -> ConduitT a c m r
.| (((AddrOutKey, OutVal) -> Bool)
-> ConduitT
     (AddrOutKey, OutVal) (AddrOutKey, OutVal) (DatabaseReaderT m) ()
forall (m :: * -> *) a o.
Monad m =>
(a -> Bool) -> ConduitT a o m ()
dropWhileC (AddrOutKey -> Bool
cond (AddrOutKey -> Bool)
-> ((AddrOutKey, OutVal) -> AddrOutKey)
-> (AddrOutKey, OutVal)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (AddrOutKey, OutVal) -> AddrOutKey
forall a b. (a, b) -> a
fst) ConduitT
  (AddrOutKey, OutVal) (AddrOutKey, OutVal) (DatabaseReaderT m) ()
-> ConduitT
     (AddrOutKey, OutVal) (AddrOutKey, OutVal) (DatabaseReaderT m) ()
-> ConduitT
     (AddrOutKey, OutVal) (AddrOutKey, OutVal) (DatabaseReaderT m) ()
forall a b.
ConduitT
  (AddrOutKey, OutVal) (AddrOutKey, OutVal) (DatabaseReaderT m) a
-> ConduitT
     (AddrOutKey, OutVal) (AddrOutKey, OutVal) (DatabaseReaderT m) b
-> ConduitT
     (AddrOutKey, OutVal) (AddrOutKey, OutVal) (DatabaseReaderT m) b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ((AddrOutKey, OutVal) -> (AddrOutKey, OutVal))
-> ConduitT
     (AddrOutKey, OutVal) (AddrOutKey, OutVal) (DatabaseReaderT m) ()
forall (m :: * -> *) a b. Monad m => (a -> b) -> ConduitT a b m ()
mapC (AddrOutKey, OutVal) -> (AddrOutKey, OutVal)
forall a. a -> a
id)
          Maybe TxData
Nothing -> () -> ConduitT i (AddrOutKey, OutVal) (DatabaseReaderT m) ()
forall a.
a -> ConduitT i (AddrOutKey, OutVal) (DatabaseReaderT m) a
forall (m :: * -> *) a. Monad m => a -> m a
return ()

withIterCFStat ::
  (MonadUnliftIO m) =>
  DB ->
  ColumnFamily ->
  (Iterator -> DatabaseReaderT m a) ->
  DatabaseReaderT m a
withIterCFStat :: forall (m :: * -> *) a.
MonadUnliftIO m =>
DB
-> ColumnFamily
-> (Iterator -> DatabaseReaderT m a)
-> DatabaseReaderT m a
withIterCFStat DB
db ColumnFamily
cf = ReaderT DatabaseReader m ()
-> ReaderT DatabaseReader m ()
-> ReaderT DatabaseReader m a
-> ReaderT DatabaseReader m a
forall (m :: * -> *) a b c.
MonadUnliftIO m =>
m a -> m b -> m c -> m c
bracket_ ReaderT DatabaseReader m ()
open ReaderT DatabaseReader m ()
close (ReaderT DatabaseReader m a -> ReaderT DatabaseReader m a)
-> ((Iterator -> ReaderT DatabaseReader m a)
    -> ReaderT DatabaseReader m a)
-> (Iterator -> ReaderT DatabaseReader m a)
-> ReaderT DatabaseReader m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DB
-> ColumnFamily
-> (Iterator -> ReaderT DatabaseReader m a)
-> ReaderT DatabaseReader m a
forall (m :: * -> *) a.
MonadUnliftIO m =>
DB -> ColumnFamily -> (Iterator -> m a) -> m a
withIterCF DB
db ColumnFamily
cf
  where
    open :: ReaderT DatabaseReader m ()
open = (DatabaseReader -> Maybe DataMetrics)
-> ReaderT DatabaseReader m (Maybe DataMetrics)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (.metrics) ReaderT DatabaseReader m (Maybe DataMetrics)
-> (Maybe DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall a b.
ReaderT DatabaseReader m a
-> (a -> ReaderT DatabaseReader m b) -> ReaderT DatabaseReader m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (DataMetrics -> ReaderT DatabaseReader m ())
-> Maybe DataMetrics -> ReaderT DatabaseReader m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (\DataMetrics
m -> StatGauge -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *). MonadIO m => StatGauge -> Int -> m ()
incrementGauge DataMetrics
m.dataIters Int
1)
    close :: ReaderT DatabaseReader m ()
close = (DatabaseReader -> Maybe DataMetrics)
-> ReaderT DatabaseReader m (Maybe DataMetrics)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (.metrics) ReaderT DatabaseReader m (Maybe DataMetrics)
-> (Maybe DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall a b.
ReaderT DatabaseReader m a
-> (a -> ReaderT DatabaseReader m b) -> ReaderT DatabaseReader m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (DataMetrics -> ReaderT DatabaseReader m ())
-> Maybe DataMetrics -> ReaderT DatabaseReader m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (\DataMetrics
m -> StatGauge -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *). MonadIO m => StatGauge -> Int -> m ()
decrementGauge DataMetrics
m.dataIters Int
1)

withManyIters ::
  (MonadUnliftIO m) =>
  DB ->
  ColumnFamily ->
  Int ->
  ([Iterator] -> DatabaseReaderT m a) ->
  DatabaseReaderT m a
withManyIters :: forall (m :: * -> *) a.
MonadUnliftIO m =>
DB
-> ColumnFamily
-> Int
-> ([Iterator] -> DatabaseReaderT m a)
-> DatabaseReaderT m a
withManyIters DB
db ColumnFamily
cf Int
i [Iterator] -> DatabaseReaderT m a
f = [Iterator] -> Int -> DatabaseReaderT m a
forall {t}. (Eq t, Num t) => [Iterator] -> t -> DatabaseReaderT m a
go [] Int
i
  where
    go :: [Iterator] -> t -> DatabaseReaderT m a
go [Iterator]
acc t
0 = [Iterator] -> DatabaseReaderT m a
f [Iterator]
acc
    go [Iterator]
acc t
n = DB
-> ColumnFamily
-> (Iterator -> DatabaseReaderT m a)
-> DatabaseReaderT m a
forall (m :: * -> *) a.
MonadUnliftIO m =>
DB
-> ColumnFamily
-> (Iterator -> DatabaseReaderT m a)
-> DatabaseReaderT m a
withIterCFStat DB
db ColumnFamily
cf ((Iterator -> DatabaseReaderT m a) -> DatabaseReaderT m a)
-> (Iterator -> DatabaseReaderT m a) -> DatabaseReaderT m a
forall a b. (a -> b) -> a -> b
$ \Iterator
it -> [Iterator] -> t -> DatabaseReaderT m a
go (Iterator
it Iterator -> [Iterator] -> [Iterator]
forall a. a -> [a] -> [a]
: [Iterator]
acc) (t
n t -> t -> t
forall a. Num a => a -> a -> a
- t
1)

joinConduits ::
  (Monad m, Ord o) =>
  [ConduitT () o m ()] ->
  Limits ->
  m [o]
joinConduits :: forall (m :: * -> *) o.
(Monad m, Ord o) =>
[ConduitT () o m ()] -> Limits -> m [o]
joinConduits [ConduitT () o m ()]
cs Limits
l =
  ConduitT () Void m [o] -> m [o]
forall (m :: * -> *) r. Monad m => ConduitT () Void m r -> m r
runConduit (ConduitT () Void m [o] -> m [o])
-> ConduitT () Void m [o] -> m [o]
forall a b. (a -> b) -> a -> b
$ [ConduitT () o m ()] -> ConduitT () o m ()
forall (m :: * -> *) a.
(Monad m, Ord a) =>
[ConduitT () a m ()] -> ConduitT () a m ()
joinDescStreams [ConduitT () o m ()]
cs ConduitT () o m ()
-> ConduitT o Void m [o] -> ConduitT () Void m [o]
forall (m :: * -> *) a b c r.
Monad m =>
ConduitT a b m () -> ConduitT b c m r -> ConduitT a c m r
.| Limits -> ConduitT o o m ()
forall (m :: * -> *) i. Monad m => Limits -> ConduitT i i m ()
applyLimitsC Limits
l ConduitT o o m () -> ConduitT o Void m [o] -> ConduitT o Void m [o]
forall (m :: * -> *) a b c r.
Monad m =>
ConduitT a b m () -> ConduitT b c m r -> ConduitT a c m r
.| ConduitT o Void m [o]
forall (m :: * -> *) a o. Monad m => ConduitT a o m [a]
sinkList

instance (MonadIO m) => StoreReadBase (DatabaseReaderT m) where
  getCtx :: DatabaseReaderT m Ctx
getCtx = (DatabaseReader -> Ctx) -> DatabaseReaderT m Ctx
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (.ctx)
  getNetwork :: DatabaseReaderT m Network
getNetwork = (DatabaseReader -> Network) -> DatabaseReaderT m Network
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (.net)

  getTxData :: TxHash -> DatabaseReaderT m (Maybe TxData)
getTxData TxHash
th = do
    DB
db <- (DatabaseReader -> DB) -> ReaderT DatabaseReader m DB
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (.db)
    DB -> ColumnFamily -> TxKey -> DatabaseReaderT m (Maybe TxData)
forall (m :: * -> *) key value.
(MonadIO m, KeyValue key value, Serialize key, Serialize value) =>
DB -> ColumnFamily -> key -> m (Maybe value)
retrieveCF DB
db (DB -> ColumnFamily
txCF DB
db) (TxHash -> TxKey
TxKey TxHash
th) DatabaseReaderT m (Maybe TxData)
-> (Maybe TxData -> DatabaseReaderT m (Maybe TxData))
-> DatabaseReaderT m (Maybe TxData)
forall a b.
ReaderT DatabaseReader m a
-> (a -> ReaderT DatabaseReader m b) -> ReaderT DatabaseReader m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
      Maybe TxData
Nothing -> Maybe TxData -> DatabaseReaderT m (Maybe TxData)
forall a. a -> ReaderT DatabaseReader m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe TxData
forall a. Maybe a
Nothing
      Just TxData
t -> do
        (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall (m :: * -> *) a.
MonadReader DatabaseReader m =>
(DataMetrics -> m a) -> m ()
withMetrics ((DataMetrics -> ReaderT DatabaseReader m ())
 -> ReaderT DatabaseReader m ())
-> (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall a b. (a -> b) -> a -> b
$ \DataMetrics
s -> StatCounter -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *). MonadIO m => StatCounter -> Int -> m ()
incrementCounter DataMetrics
s.dataTxCount Int
1
        Maybe TxData -> DatabaseReaderT m (Maybe TxData)
forall a. a -> ReaderT DatabaseReader m a
forall (m :: * -> *) a. Monad m => a -> m a
return (TxData -> Maybe TxData
forall a. a -> Maybe a
Just TxData
t)

  getSpender :: OutPoint -> DatabaseReaderT m (Maybe Spender)
getSpender OutPoint
op = MaybeT (DatabaseReaderT m) Spender
-> DatabaseReaderT m (Maybe Spender)
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT (MaybeT (DatabaseReaderT m) Spender
 -> DatabaseReaderT m (Maybe Spender))
-> MaybeT (DatabaseReaderT m) Spender
-> DatabaseReaderT m (Maybe Spender)
forall a b. (a -> b) -> a -> b
$ do
    TxData
td <- DatabaseReaderT m (Maybe TxData)
-> MaybeT (DatabaseReaderT m) TxData
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (DatabaseReaderT m (Maybe TxData)
 -> MaybeT (DatabaseReaderT m) TxData)
-> DatabaseReaderT m (Maybe TxData)
-> MaybeT (DatabaseReaderT m) TxData
forall a b. (a -> b) -> a -> b
$ TxHash -> DatabaseReaderT m (Maybe TxData)
forall (m :: * -> *). StoreReadBase m => TxHash -> m (Maybe TxData)
getTxData OutPoint
op.hash
    let i :: Int
i = Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral OutPoint
op.index
    DatabaseReaderT m (Maybe Spender)
-> MaybeT (DatabaseReaderT m) Spender
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (DatabaseReaderT m (Maybe Spender)
 -> MaybeT (DatabaseReaderT m) Spender)
-> (Maybe Spender -> DatabaseReaderT m (Maybe Spender))
-> Maybe Spender
-> MaybeT (DatabaseReaderT m) Spender
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe Spender -> DatabaseReaderT m (Maybe Spender)
forall a. a -> ReaderT DatabaseReader m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe Spender -> MaybeT (DatabaseReaderT m) Spender)
-> Maybe Spender -> MaybeT (DatabaseReaderT m) Spender
forall a b. (a -> b) -> a -> b
$ Int
i Int -> IntMap Spender -> Maybe Spender
forall a. Int -> IntMap a -> Maybe a
`IntMap.lookup` TxData
td.spenders

  getUnspent :: OutPoint -> DatabaseReaderT m (Maybe Unspent)
getUnspent OutPoint
p = do
    DB
db <- (DatabaseReader -> DB) -> ReaderT DatabaseReader m DB
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (.db)
    Ctx
ctx <- (DatabaseReader -> Ctx) -> DatabaseReaderT m Ctx
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (.ctx)
    Maybe UnspentVal
val <- DB
-> ColumnFamily
-> UnspentKey
-> ReaderT DatabaseReader m (Maybe UnspentVal)
forall (m :: * -> *) key value.
(MonadIO m, KeyValue key value, Serialize key, Serialize value) =>
DB -> ColumnFamily -> key -> m (Maybe value)
retrieveCF DB
db (DB -> ColumnFamily
unspentCF DB
db) (OutPoint -> UnspentKey
UnspentKey OutPoint
p)
    case (UnspentVal -> Unspent) -> Maybe UnspentVal -> Maybe Unspent
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Ctx -> OutPoint -> UnspentVal -> Unspent
valToUnspent Ctx
ctx OutPoint
p) Maybe UnspentVal
val of
      Maybe Unspent
Nothing -> Maybe Unspent -> DatabaseReaderT m (Maybe Unspent)
forall a. a -> ReaderT DatabaseReader m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Unspent
forall a. Maybe a
Nothing
      Just Unspent
u -> do
        (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall (m :: * -> *) a.
MonadReader DatabaseReader m =>
(DataMetrics -> m a) -> m ()
withMetrics ((DataMetrics -> ReaderT DatabaseReader m ())
 -> ReaderT DatabaseReader m ())
-> (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall a b. (a -> b) -> a -> b
$ \DataMetrics
s -> StatCounter -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *). MonadIO m => StatCounter -> Int -> m ()
incrementCounter DataMetrics
s.dataUnspentCount Int
1
        Maybe Unspent -> DatabaseReaderT m (Maybe Unspent)
forall a. a -> ReaderT DatabaseReader m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Unspent -> Maybe Unspent
forall a. a -> Maybe a
Just Unspent
u)

  getBalance :: Address -> DatabaseReaderT m (Maybe Balance)
getBalance Address
a = do
    DB
db <- (DatabaseReader -> DB) -> ReaderT DatabaseReader m DB
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (.db)
    (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall (m :: * -> *) a.
MonadReader DatabaseReader m =>
(DataMetrics -> m a) -> m ()
withMetrics ((DataMetrics -> ReaderT DatabaseReader m ())
 -> ReaderT DatabaseReader m ())
-> (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall a b. (a -> b) -> a -> b
$ \DataMetrics
s -> StatCounter -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *). MonadIO m => StatCounter -> Int -> m ()
incrementCounter DataMetrics
s.dataBalanceCount Int
1
    (BalVal -> Balance) -> Maybe BalVal -> Maybe Balance
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Address -> BalVal -> Balance
valToBalance Address
a) (Maybe BalVal -> Maybe Balance)
-> ReaderT DatabaseReader m (Maybe BalVal)
-> DatabaseReaderT m (Maybe Balance)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DB
-> ColumnFamily
-> BalKey
-> ReaderT DatabaseReader m (Maybe BalVal)
forall (m :: * -> *) key value.
(MonadIO m, KeyValue key value, Serialize key, Serialize value) =>
DB -> ColumnFamily -> key -> m (Maybe value)
retrieveCF DB
db (DB -> ColumnFamily
balanceCF DB
db) (Address -> BalKey
BalKey Address
a)

  getMempool :: DatabaseReaderT m [(UnixTime, TxHash)]
getMempool = do
    DB
db <- (DatabaseReader -> DB) -> ReaderT DatabaseReader m DB
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (.db)
    (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall (m :: * -> *) a.
MonadReader DatabaseReader m =>
(DataMetrics -> m a) -> m ()
withMetrics ((DataMetrics -> ReaderT DatabaseReader m ())
 -> ReaderT DatabaseReader m ())
-> (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall a b. (a -> b) -> a -> b
$ \DataMetrics
s -> StatCounter -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *). MonadIO m => StatCounter -> Int -> m ()
incrementCounter DataMetrics
s.dataMempoolCount Int
1
    [(UnixTime, TxHash)]
-> Maybe [(UnixTime, TxHash)] -> [(UnixTime, TxHash)]
forall a. a -> Maybe a -> a
fromMaybe [] (Maybe [(UnixTime, TxHash)] -> [(UnixTime, TxHash)])
-> ReaderT DatabaseReader m (Maybe [(UnixTime, TxHash)])
-> DatabaseReaderT m [(UnixTime, TxHash)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DB
-> MemKey -> ReaderT DatabaseReader m (Maybe [(UnixTime, TxHash)])
forall (m :: * -> *) key value.
(MonadIO m, KeyValue key value, Serialize key, Serialize value) =>
DB -> key -> m (Maybe value)
retrieve DB
db MemKey
MemKey

  getBestBlock :: DatabaseReaderT m (Maybe BlockHash)
getBestBlock = do
    (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall (m :: * -> *) a.
MonadReader DatabaseReader m =>
(DataMetrics -> m a) -> m ()
withMetrics ((DataMetrics -> ReaderT DatabaseReader m ())
 -> ReaderT DatabaseReader m ())
-> (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall a b. (a -> b) -> a -> b
$ \DataMetrics
s -> StatCounter -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *). MonadIO m => StatCounter -> Int -> m ()
incrementCounter DataMetrics
s.dataBestCount Int
1
    (DatabaseReader -> DB) -> ReaderT DatabaseReader m DB
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (.db) ReaderT DatabaseReader m DB
-> (DB -> DatabaseReaderT m (Maybe BlockHash))
-> DatabaseReaderT m (Maybe BlockHash)
forall a b.
ReaderT DatabaseReader m a
-> (a -> ReaderT DatabaseReader m b) -> ReaderT DatabaseReader m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (DB -> BestKey -> DatabaseReaderT m (Maybe BlockHash)
forall (m :: * -> *) key value.
(MonadIO m, KeyValue key value, Serialize key, Serialize value) =>
DB -> key -> m (Maybe value)
`retrieve` BestKey
BestKey)

  getBlocksAtHeight :: Word32 -> DatabaseReaderT m [BlockHash]
getBlocksAtHeight Word32
h = do
    DB
db <- (DatabaseReader -> DB) -> ReaderT DatabaseReader m DB
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (.db)
    DB
-> ColumnFamily
-> HeightKey
-> ReaderT DatabaseReader m (Maybe [BlockHash])
forall (m :: * -> *) key value.
(MonadIO m, KeyValue key value, Serialize key, Serialize value) =>
DB -> ColumnFamily -> key -> m (Maybe value)
retrieveCF DB
db (DB -> ColumnFamily
heightCF DB
db) (Word32 -> HeightKey
HeightKey Word32
h) ReaderT DatabaseReader m (Maybe [BlockHash])
-> (Maybe [BlockHash] -> DatabaseReaderT m [BlockHash])
-> DatabaseReaderT m [BlockHash]
forall a b.
ReaderT DatabaseReader m a
-> (a -> ReaderT DatabaseReader m b) -> ReaderT DatabaseReader m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
      Maybe [BlockHash]
Nothing -> [BlockHash] -> DatabaseReaderT m [BlockHash]
forall a. a -> ReaderT DatabaseReader m a
forall (m :: * -> *) a. Monad m => a -> m a
return []
      Just [BlockHash]
ls -> do
        (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall (m :: * -> *) a.
MonadReader DatabaseReader m =>
(DataMetrics -> m a) -> m ()
withMetrics ((DataMetrics -> ReaderT DatabaseReader m ())
 -> ReaderT DatabaseReader m ())
-> (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall a b. (a -> b) -> a -> b
$ \DataMetrics
s -> StatCounter -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *). MonadIO m => StatCounter -> Int -> m ()
incrementCounter DataMetrics
s.dataBlockCount ([BlockHash] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [BlockHash]
ls)
        [BlockHash] -> DatabaseReaderT m [BlockHash]
forall a. a -> ReaderT DatabaseReader m a
forall (m :: * -> *) a. Monad m => a -> m a
return [BlockHash]
ls

  getBlock :: BlockHash -> DatabaseReaderT m (Maybe BlockData)
getBlock BlockHash
h = do
    DB
db <- (DatabaseReader -> DB) -> ReaderT DatabaseReader m DB
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (.db)
    DB
-> ColumnFamily -> BlockKey -> DatabaseReaderT m (Maybe BlockData)
forall (m :: * -> *) key value.
(MonadIO m, KeyValue key value, Serialize key, Serialize value) =>
DB -> ColumnFamily -> key -> m (Maybe value)
retrieveCF DB
db (DB -> ColumnFamily
blockCF DB
db) (BlockHash -> BlockKey
BlockKey BlockHash
h) DatabaseReaderT m (Maybe BlockData)
-> (Maybe BlockData -> DatabaseReaderT m (Maybe BlockData))
-> DatabaseReaderT m (Maybe BlockData)
forall a b.
ReaderT DatabaseReader m a
-> (a -> ReaderT DatabaseReader m b) -> ReaderT DatabaseReader m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
      Maybe BlockData
Nothing -> Maybe BlockData -> DatabaseReaderT m (Maybe BlockData)
forall a. a -> ReaderT DatabaseReader m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe BlockData
forall a. Maybe a
Nothing
      Just BlockData
b -> do
        (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall (m :: * -> *) a.
MonadReader DatabaseReader m =>
(DataMetrics -> m a) -> m ()
withMetrics ((DataMetrics -> ReaderT DatabaseReader m ())
 -> ReaderT DatabaseReader m ())
-> (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall a b. (a -> b) -> a -> b
$ \DataMetrics
s -> StatCounter -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *). MonadIO m => StatCounter -> Int -> m ()
incrementCounter DataMetrics
s.dataBlockCount Int
1
        Maybe BlockData -> DatabaseReaderT m (Maybe BlockData)
forall a. a -> ReaderT DatabaseReader m a
forall (m :: * -> *) a. Monad m => a -> m a
return (BlockData -> Maybe BlockData
forall a. a -> Maybe a
Just BlockData
b)

instance (MonadUnliftIO m) => StoreReadExtra (DatabaseReaderT m) where
  getAddressesTxs :: [Address] -> Limits -> DatabaseReaderT m [TxRef]
getAddressesTxs [Address]
addrs Limits
limits = do
    DB
db <- (DatabaseReader -> DB) -> ReaderT DatabaseReader m DB
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (.db)
    DB
-> ColumnFamily
-> Int
-> ([Iterator] -> DatabaseReaderT m [TxRef])
-> DatabaseReaderT m [TxRef]
forall (m :: * -> *) a.
MonadUnliftIO m =>
DB
-> ColumnFamily
-> Int
-> ([Iterator] -> DatabaseReaderT m a)
-> DatabaseReaderT m a
withManyIters DB
db (DB -> ColumnFamily
addrTxCF DB
db) ([Address] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Address]
addrs) (([Iterator] -> DatabaseReaderT m [TxRef])
 -> DatabaseReaderT m [TxRef])
-> ([Iterator] -> DatabaseReaderT m [TxRef])
-> DatabaseReaderT m [TxRef]
forall a b. (a -> b) -> a -> b
$ \[Iterator]
its -> do
      [TxRef]
txs <- [ConduitT () TxRef (DatabaseReaderT m) ()]
-> Limits -> DatabaseReaderT m [TxRef]
forall (m :: * -> *) o.
(Monad m, Ord o) =>
[ConduitT () o m ()] -> Limits -> m [o]
joinConduits ([Iterator] -> [ConduitT () TxRef (DatabaseReaderT m) ()]
forall {i}. [Iterator] -> [ConduitT i TxRef (DatabaseReaderT m) ()]
cs [Iterator]
its) Limits
limits
      (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall (m :: * -> *) a.
MonadReader DatabaseReader m =>
(DataMetrics -> m a) -> m ()
withMetrics ((DataMetrics -> ReaderT DatabaseReader m ())
 -> ReaderT DatabaseReader m ())
-> (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall a b. (a -> b) -> a -> b
$ \DataMetrics
s -> StatCounter -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *). MonadIO m => StatCounter -> Int -> m ()
incrementCounter DataMetrics
s.dataAddrTxCount ([TxRef] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [TxRef]
txs)
      [TxRef] -> DatabaseReaderT m [TxRef]
forall a. a -> ReaderT DatabaseReader m a
forall (m :: * -> *) a. Monad m => a -> m a
return [TxRef]
txs
    where
      cs :: [Iterator] -> [ConduitT i TxRef (DatabaseReaderT m) ()]
cs = (Address -> Iterator -> ConduitT i TxRef (DatabaseReaderT m) ())
-> [Address]
-> [Iterator]
-> [ConduitT i TxRef (DatabaseReaderT m) ()]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Address -> Iterator -> ConduitT i TxRef (DatabaseReaderT m) ()
forall {m :: * -> *} {i}.
MonadUnliftIO m =>
Address -> Iterator -> ConduitT i TxRef (DatabaseReaderT m) ()
c [Address]
addrs
      c :: Address -> Iterator -> ConduitT i TxRef (DatabaseReaderT m) ()
c Address
a = Address
-> Maybe Start
-> Iterator
-> ConduitT i TxRef (DatabaseReaderT m) ()
forall (m :: * -> *) i.
MonadUnliftIO m =>
Address
-> Maybe Start
-> Iterator
-> ConduitT i TxRef (DatabaseReaderT m) ()
addressConduit Address
a Limits
limits.start

  getAddressesUnspents :: [Address] -> Limits -> DatabaseReaderT m [Unspent]
getAddressesUnspents [Address]
addrs Limits
limits = do
    DB
db <- (DatabaseReader -> DB) -> ReaderT DatabaseReader m DB
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (.db)
    Ctx
ctx <- (DatabaseReader -> Ctx) -> ReaderT DatabaseReader m Ctx
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (.ctx)
    DB
-> ColumnFamily
-> Int
-> ([Iterator] -> DatabaseReaderT m [Unspent])
-> DatabaseReaderT m [Unspent]
forall (m :: * -> *) a.
MonadUnliftIO m =>
DB
-> ColumnFamily
-> Int
-> ([Iterator] -> DatabaseReaderT m a)
-> DatabaseReaderT m a
withManyIters DB
db (DB -> ColumnFamily
addrOutCF DB
db) ([Address] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Address]
addrs) (([Iterator] -> DatabaseReaderT m [Unspent])
 -> DatabaseReaderT m [Unspent])
-> ([Iterator] -> DatabaseReaderT m [Unspent])
-> DatabaseReaderT m [Unspent]
forall a b. (a -> b) -> a -> b
$ \[Iterator]
its -> do
      [Unspent]
uns <- [ConduitT () Unspent (DatabaseReaderT m) ()]
-> Limits -> DatabaseReaderT m [Unspent]
forall (m :: * -> *) o.
(Monad m, Ord o) =>
[ConduitT () o m ()] -> Limits -> m [o]
joinConduits (Ctx -> [Iterator] -> [ConduitT () Unspent (DatabaseReaderT m) ()]
forall {m :: * -> *} {i}.
MonadUnliftIO m =>
Ctx -> [Iterator] -> [ConduitT i Unspent (DatabaseReaderT m) ()]
cs Ctx
ctx [Iterator]
its) Limits
limits
      (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall (m :: * -> *) a.
MonadReader DatabaseReader m =>
(DataMetrics -> m a) -> m ()
withMetrics ((DataMetrics -> ReaderT DatabaseReader m ())
 -> ReaderT DatabaseReader m ())
-> (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall a b. (a -> b) -> a -> b
$ \DataMetrics
s -> StatCounter -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *). MonadIO m => StatCounter -> Int -> m ()
incrementCounter DataMetrics
s.dataUnspentCount ([Unspent] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Unspent]
uns)
      [Unspent] -> DatabaseReaderT m [Unspent]
forall a. a -> ReaderT DatabaseReader m a
forall (m :: * -> *) a. Monad m => a -> m a
return [Unspent]
uns
    where
      cs :: Ctx -> [Iterator] -> [ConduitT i Unspent (DatabaseReaderT m) ()]
cs Ctx
ctx = (Address -> Iterator -> ConduitT i Unspent (DatabaseReaderT m) ())
-> [Address]
-> [Iterator]
-> [ConduitT i Unspent (DatabaseReaderT m) ()]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (Ctx
-> Address -> Iterator -> ConduitT i Unspent (DatabaseReaderT m) ()
forall {m :: * -> *} {i}.
MonadUnliftIO m =>
Ctx
-> Address -> Iterator -> ConduitT i Unspent (DatabaseReaderT m) ()
c Ctx
ctx) [Address]
addrs
      c :: Ctx
-> Address -> Iterator -> ConduitT i Unspent (DatabaseReaderT m) ()
c Ctx
ctx Address
a = Ctx
-> Address
-> Maybe Start
-> Iterator
-> ConduitT i Unspent (DatabaseReaderT m) ()
forall (m :: * -> *) i.
MonadUnliftIO m =>
Ctx
-> Address
-> Maybe Start
-> Iterator
-> ConduitT i Unspent (DatabaseReaderT m) ()
unspentConduit Ctx
ctx Address
a Limits
limits.start

  getAddressUnspents :: Address -> Limits -> DatabaseReaderT m [Unspent]
getAddressUnspents Address
a Limits
limits = do
    DB
db <- (DatabaseReader -> DB) -> ReaderT DatabaseReader m DB
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (.db)
    Ctx
ctx <- (DatabaseReader -> Ctx) -> ReaderT DatabaseReader m Ctx
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (.ctx)
    [Unspent]
us <- DB
-> ColumnFamily
-> (Iterator -> DatabaseReaderT m [Unspent])
-> DatabaseReaderT m [Unspent]
forall (m :: * -> *) a.
MonadUnliftIO m =>
DB
-> ColumnFamily
-> (Iterator -> DatabaseReaderT m a)
-> DatabaseReaderT m a
withIterCFStat DB
db (DB -> ColumnFamily
addrOutCF DB
db) ((Iterator -> DatabaseReaderT m [Unspent])
 -> DatabaseReaderT m [Unspent])
-> (Iterator -> DatabaseReaderT m [Unspent])
-> DatabaseReaderT m [Unspent]
forall a b. (a -> b) -> a -> b
$ \Iterator
it ->
      ConduitT () Void (DatabaseReaderT m) [Unspent]
-> DatabaseReaderT m [Unspent]
forall (m :: * -> *) r. Monad m => ConduitT () Void m r -> m r
runConduit (ConduitT () Void (DatabaseReaderT m) [Unspent]
 -> DatabaseReaderT m [Unspent])
-> ConduitT () Void (DatabaseReaderT m) [Unspent]
-> DatabaseReaderT m [Unspent]
forall a b. (a -> b) -> a -> b
$
        Ctx
-> Address
-> Maybe Start
-> Iterator
-> ConduitT () Unspent (DatabaseReaderT m) ()
forall (m :: * -> *) i.
MonadUnliftIO m =>
Ctx
-> Address
-> Maybe Start
-> Iterator
-> ConduitT i Unspent (DatabaseReaderT m) ()
unspentConduit Ctx
ctx Address
a Limits
limits.start Iterator
it
          ConduitT () Unspent (DatabaseReaderT m) ()
-> ConduitT Unspent Void (DatabaseReaderT m) [Unspent]
-> ConduitT () Void (DatabaseReaderT m) [Unspent]
forall (m :: * -> *) a b c r.
Monad m =>
ConduitT a b m () -> ConduitT b c m r -> ConduitT a c m r
.| Limits -> ConduitT Unspent Unspent (DatabaseReaderT m) ()
forall (m :: * -> *) i. Monad m => Limits -> ConduitT i i m ()
applyLimitsC Limits
limits
          ConduitT Unspent Unspent (DatabaseReaderT m) ()
-> ConduitT Unspent Void (DatabaseReaderT m) [Unspent]
-> ConduitT Unspent Void (DatabaseReaderT m) [Unspent]
forall (m :: * -> *) a b c r.
Monad m =>
ConduitT a b m () -> ConduitT b c m r -> ConduitT a c m r
.| ConduitT Unspent Void (DatabaseReaderT m) [Unspent]
forall (m :: * -> *) a o. Monad m => ConduitT a o m [a]
sinkList
    (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall (m :: * -> *) a.
MonadReader DatabaseReader m =>
(DataMetrics -> m a) -> m ()
withMetrics ((DataMetrics -> ReaderT DatabaseReader m ())
 -> ReaderT DatabaseReader m ())
-> (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall a b. (a -> b) -> a -> b
$ \DataMetrics
s -> StatCounter -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *). MonadIO m => StatCounter -> Int -> m ()
incrementCounter DataMetrics
s.dataUnspentCount ([Unspent] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Unspent]
us)
    [Unspent] -> DatabaseReaderT m [Unspent]
forall a. a -> ReaderT DatabaseReader m a
forall (m :: * -> *) a. Monad m => a -> m a
return [Unspent]
us

  getAddressTxs :: Address -> Limits -> DatabaseReaderT m [TxRef]
getAddressTxs Address
a Limits
limits = do
    DB
db <- (DatabaseReader -> DB) -> ReaderT DatabaseReader m DB
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (.db)
    [TxRef]
txs <- DB
-> ColumnFamily
-> (Iterator -> DatabaseReaderT m [TxRef])
-> DatabaseReaderT m [TxRef]
forall (m :: * -> *) a.
MonadUnliftIO m =>
DB
-> ColumnFamily
-> (Iterator -> DatabaseReaderT m a)
-> DatabaseReaderT m a
withIterCFStat DB
db (DB -> ColumnFamily
addrTxCF DB
db) ((Iterator -> DatabaseReaderT m [TxRef])
 -> DatabaseReaderT m [TxRef])
-> (Iterator -> DatabaseReaderT m [TxRef])
-> DatabaseReaderT m [TxRef]
forall a b. (a -> b) -> a -> b
$ \Iterator
it ->
      ConduitT () Void (DatabaseReaderT m) [TxRef]
-> DatabaseReaderT m [TxRef]
forall (m :: * -> *) r. Monad m => ConduitT () Void m r -> m r
runConduit (ConduitT () Void (DatabaseReaderT m) [TxRef]
 -> DatabaseReaderT m [TxRef])
-> ConduitT () Void (DatabaseReaderT m) [TxRef]
-> DatabaseReaderT m [TxRef]
forall a b. (a -> b) -> a -> b
$
        Address
-> Maybe Start
-> Iterator
-> ConduitT () TxRef (DatabaseReaderT m) ()
forall (m :: * -> *) i.
MonadUnliftIO m =>
Address
-> Maybe Start
-> Iterator
-> ConduitT i TxRef (DatabaseReaderT m) ()
addressConduit Address
a Limits
limits.start Iterator
it
          ConduitT () TxRef (DatabaseReaderT m) ()
-> ConduitT TxRef Void (DatabaseReaderT m) [TxRef]
-> ConduitT () Void (DatabaseReaderT m) [TxRef]
forall (m :: * -> *) a b c r.
Monad m =>
ConduitT a b m () -> ConduitT b c m r -> ConduitT a c m r
.| Limits -> ConduitT TxRef TxRef (DatabaseReaderT m) ()
forall (m :: * -> *) i. Monad m => Limits -> ConduitT i i m ()
applyLimitsC Limits
limits
          ConduitT TxRef TxRef (DatabaseReaderT m) ()
-> ConduitT TxRef Void (DatabaseReaderT m) [TxRef]
-> ConduitT TxRef Void (DatabaseReaderT m) [TxRef]
forall (m :: * -> *) a b c r.
Monad m =>
ConduitT a b m () -> ConduitT b c m r -> ConduitT a c m r
.| ConduitT TxRef Void (DatabaseReaderT m) [TxRef]
forall (m :: * -> *) a o. Monad m => ConduitT a o m [a]
sinkList
    (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall (m :: * -> *) a.
MonadReader DatabaseReader m =>
(DataMetrics -> m a) -> m ()
withMetrics ((DataMetrics -> ReaderT DatabaseReader m ())
 -> ReaderT DatabaseReader m ())
-> (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall a b. (a -> b) -> a -> b
$ \DataMetrics
s -> StatCounter -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *). MonadIO m => StatCounter -> Int -> m ()
incrementCounter DataMetrics
s.dataAddrTxCount ([TxRef] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [TxRef]
txs)
    [TxRef] -> DatabaseReaderT m [TxRef]
forall a. a -> ReaderT DatabaseReader m a
forall (m :: * -> *) a. Monad m => a -> m a
return [TxRef]
txs

  getMaxGap :: DatabaseReaderT m Word32
getMaxGap = (DatabaseReader -> Word32) -> DatabaseReaderT m Word32
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (.maxGap)

  getInitialGap :: DatabaseReaderT m Word32
getInitialGap = (DatabaseReader -> Word32) -> DatabaseReaderT m Word32
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (.initGap)

  getNumTxData :: UnixTime -> DatabaseReaderT m [TxData]
getNumTxData UnixTime
i = do
    DB
db <- (DatabaseReader -> DB) -> ReaderT DatabaseReader m DB
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (.db)
    let ((Word32, Word16)
sk, Word8
w) = UnixTime -> ((Word32, Word16), Word8)
decodeTxKey UnixTime
i
    [(TxKey, TxData)]
ls <- IO [(TxKey, TxData)] -> ReaderT DatabaseReader m [(TxKey, TxData)]
forall a. IO a -> ReaderT DatabaseReader m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [(TxKey, TxData)]
 -> ReaderT DatabaseReader m [(TxKey, TxData)])
-> IO [(TxKey, TxData)]
-> ReaderT DatabaseReader m [(TxKey, TxData)]
forall a b. (a -> b) -> a -> b
$ DB -> ColumnFamily -> TxKey -> IO [(TxKey, TxData)]
forall (m :: * -> *) key value.
(MonadUnliftIO m, KeyValue key value, Serialize key,
 Serialize value) =>
DB -> ColumnFamily -> key -> m [(key, value)]
matchingAsListCF DB
db (DB -> ColumnFamily
txCF DB
db) ((Word32, Word16) -> TxKey
TxKeyS (Word32, Word16)
sk)
    let f :: p -> Bool
f p
t =
          let bs :: ByteString
bs = TxHash -> ByteString
forall a. Serialize a => a -> ByteString
encode (TxHash -> ByteString) -> TxHash -> ByteString
forall a b. (a -> b) -> a -> b
$ Tx -> TxHash
txHash p
t.tx
              b :: Word8
b = HasCallStack => ByteString -> Word8
ByteString -> Word8
BS.head (Int -> ByteString -> ByteString
BS.drop Int
6 ByteString
bs)
              w' :: Word8
w' = Word8
b Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0xf8
           in Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
w'
        txs :: [TxData]
txs = (TxData -> Bool) -> [TxData] -> [TxData]
forall a. (a -> Bool) -> [a] -> [a]
filter TxData -> Bool
forall {p}. HasField "tx" p Tx => p -> Bool
f ([TxData] -> [TxData]) -> [TxData] -> [TxData]
forall a b. (a -> b) -> a -> b
$ ((TxKey, TxData) -> TxData) -> [(TxKey, TxData)] -> [TxData]
forall a b. (a -> b) -> [a] -> [b]
map (TxKey, TxData) -> TxData
forall a b. (a, b) -> b
snd [(TxKey, TxData)]
ls
    (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall (m :: * -> *) a.
MonadReader DatabaseReader m =>
(DataMetrics -> m a) -> m ()
withMetrics ((DataMetrics -> ReaderT DatabaseReader m ())
 -> ReaderT DatabaseReader m ())
-> (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall a b. (a -> b) -> a -> b
$ \DataMetrics
s -> StatCounter -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *). MonadIO m => StatCounter -> Int -> m ()
incrementCounter DataMetrics
s.dataTxCount ([TxData] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [TxData]
txs)
    [TxData] -> DatabaseReaderT m [TxData]
forall a. a -> ReaderT DatabaseReader m a
forall (m :: * -> *) a. Monad m => a -> m a
return [TxData]
txs

  getBalances :: [Address] -> DatabaseReaderT m [Balance]
getBalances [Address]
as = do
    (Address -> Maybe Balance -> Balance)
-> [Address] -> [Maybe Balance] -> [Balance]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Address -> Maybe Balance -> Balance
f [Address]
as ([Maybe Balance] -> [Balance])
-> ReaderT DatabaseReader m [Maybe Balance]
-> DatabaseReaderT m [Balance]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Address -> ReaderT DatabaseReader m (Maybe Balance))
-> [Address] -> ReaderT DatabaseReader m [Maybe Balance]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM Address -> ReaderT DatabaseReader m (Maybe Balance)
forall (m :: * -> *).
StoreReadBase m =>
Address -> m (Maybe Balance)
getBalance [Address]
as
    where
      f :: Address -> Maybe Balance -> Balance
f Address
a Maybe Balance
Nothing = Address -> Balance
zeroBalance Address
a
      f Address
_ (Just Balance
b) = Balance
b

  xPubBals :: XPubSpec -> DatabaseReaderT m [XPubBal]
xPubBals XPubSpec
xpub = do
    Ctx
ctx <- (DatabaseReader -> Ctx) -> ReaderT DatabaseReader m Ctx
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (.ctx)
    Word32
igap <- DatabaseReaderT m Word32
forall (m :: * -> *). StoreReadExtra m => m Word32
getInitialGap
    Word32
gap <- DatabaseReaderT m Word32
forall (m :: * -> *). StoreReadExtra m => m Word32
getMaxGap
    [XPubBal]
ext1 <- Word32
-> Word32 -> [(Word32, Address)] -> DatabaseReaderT m [XPubBal]
forall {m :: * -> *} {p}.
(StoreReadExtra m, Integral p) =>
p -> Word32 -> [(Word32, Address)] -> m [XPubBal]
derive_until_gap Word32
gap Word32
0 (Int -> [(Word32, Address)] -> [(Word32, Address)]
forall a. Int -> [a] -> [a]
take (Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
igap) (Ctx -> Word32 -> Word32 -> [(Word32, Address)]
aderiv Ctx
ctx Word32
0 Word32
0))
    if (XPubBal -> Bool) -> [XPubBal] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all XPubBal -> Bool
forall {r}. HasField "balance" r Balance => r -> Bool
nullxb [XPubBal]
ext1
      then do
        (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall (m :: * -> *) a.
MonadReader DatabaseReader m =>
(DataMetrics -> m a) -> m ()
withMetrics ((DataMetrics -> ReaderT DatabaseReader m ())
 -> ReaderT DatabaseReader m ())
-> (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall a b. (a -> b) -> a -> b
$ \DataMetrics
s -> StatCounter -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *). MonadIO m => StatCounter -> Int -> m ()
incrementCounter DataMetrics
s.dataXPubBals ([XPubBal] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [XPubBal]
ext1)
        [XPubBal] -> DatabaseReaderT m [XPubBal]
forall a. a -> ReaderT DatabaseReader m a
forall (m :: * -> *) a. Monad m => a -> m a
return [XPubBal]
ext1
      else do
        [XPubBal]
ext2 <- Word32
-> Word32 -> [(Word32, Address)] -> DatabaseReaderT m [XPubBal]
forall {m :: * -> *} {p}.
(StoreReadExtra m, Integral p) =>
p -> Word32 -> [(Word32, Address)] -> m [XPubBal]
derive_until_gap Word32
gap Word32
0 (Ctx -> Word32 -> Word32 -> [(Word32, Address)]
aderiv Ctx
ctx Word32
0 Word32
igap)
        [XPubBal]
chg <- Word32
-> Word32 -> [(Word32, Address)] -> DatabaseReaderT m [XPubBal]
forall {m :: * -> *} {p}.
(StoreReadExtra m, Integral p) =>
p -> Word32 -> [(Word32, Address)] -> m [XPubBal]
derive_until_gap Word32
gap Word32
1 (Ctx -> Word32 -> Word32 -> [(Word32, Address)]
aderiv Ctx
ctx Word32
1 Word32
0)
        let bals :: [XPubBal]
bals = [XPubBal]
ext1 [XPubBal] -> [XPubBal] -> [XPubBal]
forall a. Semigroup a => a -> a -> a
<> [XPubBal]
ext2 [XPubBal] -> [XPubBal] -> [XPubBal]
forall a. Semigroup a => a -> a -> a
<> [XPubBal]
chg
        (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall (m :: * -> *) a.
MonadReader DatabaseReader m =>
(DataMetrics -> m a) -> m ()
withMetrics ((DataMetrics -> ReaderT DatabaseReader m ())
 -> ReaderT DatabaseReader m ())
-> (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall a b. (a -> b) -> a -> b
$ \DataMetrics
s -> StatCounter -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *). MonadIO m => StatCounter -> Int -> m ()
incrementCounter DataMetrics
s.dataXPubBals ([XPubBal] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [XPubBal]
bals)
        [XPubBal] -> DatabaseReaderT m [XPubBal]
forall a. a -> ReaderT DatabaseReader m a
forall (m :: * -> *) a. Monad m => a -> m a
return [XPubBal]
bals
    where
      nullxb :: r -> Bool
nullxb r
b = Balance -> Bool
nullBalance r
b.balance
      aderiv :: Ctx -> Word32 -> Word32 -> [(Word32, Address)]
aderiv Ctx
ctx Word32
m =
        DeriveAddr -> XPubKey -> Word32 -> [(Word32, Address)]
deriveAddresses
          (Ctx -> DeriveType -> DeriveAddr
deriveFunction Ctx
ctx XPubSpec
xpub.deriv)
          (Ctx -> XPubKey -> Word32 -> XPubKey
pubSubKey Ctx
ctx XPubSpec
xpub.key Word32
m)
      derive_until_gap :: p -> Word32 -> [(Word32, Address)] -> m [XPubBal]
derive_until_gap p
gap Word32
m [(Word32, Address)]
adrs =
        let xb :: Balance -> Word32 -> XPubBal
xb Balance
b Word32
n = XPubBal {$sel:path:XPubBal :: [Word32]
path = [Word32
m, Word32
n], $sel:balance:XPubBal :: Balance
balance = Balance
b}
            ig :: Int
ig = p -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral p
gap
            test :: [a] -> Bool
test [a]
acc =
              let ns :: [a]
ns = (a -> Bool) -> [a] -> [a]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile a -> Bool
forall {r}. HasField "balance" r Balance => r -> Bool
nullxb [a]
acc
               in [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
ns Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
ig
            go :: [XPubBal] -> [(Word32, Address)] -> m [XPubBal]
go [XPubBal]
acc [] = [XPubBal] -> m [XPubBal]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([XPubBal] -> m [XPubBal]) -> [XPubBal] -> m [XPubBal]
forall a b. (a -> b) -> a -> b
$ [XPubBal] -> [XPubBal]
forall a. [a] -> [a]
reverse [XPubBal]
acc
            go [XPubBal]
acc [(Word32, Address)]
as
              | [XPubBal] -> Bool
forall {a}. HasField "balance" a Balance => [a] -> Bool
test [XPubBal]
acc =
                  let ([XPubBal]
ns, [XPubBal]
ys) = (XPubBal -> Bool) -> [XPubBal] -> ([XPubBal], [XPubBal])
forall a. (a -> Bool) -> [a] -> ([a], [a])
span XPubBal -> Bool
forall {r}. HasField "balance" r Balance => r -> Bool
nullxb [XPubBal]
acc
                      xs :: [XPubBal]
xs = Int -> [XPubBal] -> [XPubBal]
forall a. Int -> [a] -> [a]
take Int
ig ([XPubBal] -> [XPubBal]) -> [XPubBal] -> [XPubBal]
forall a b. (a -> b) -> a -> b
$ [XPubBal] -> [XPubBal]
forall a. [a] -> [a]
reverse [XPubBal]
ns
                   in [XPubBal] -> m [XPubBal]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([XPubBal] -> m [XPubBal]) -> [XPubBal] -> m [XPubBal]
forall a b. (a -> b) -> a -> b
$ [XPubBal] -> [XPubBal]
forall a. [a] -> [a]
reverse [XPubBal]
ys [XPubBal] -> [XPubBal] -> [XPubBal]
forall a. Semigroup a => a -> a -> a
<> [XPubBal]
xs
              | Bool
otherwise = do
                  let ([(Word32, Address)]
as', [(Word32, Address)]
as'') = Int
-> [(Word32, Address)]
-> ([(Word32, Address)], [(Word32, Address)])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
ig [(Word32, Address)]
as
                  [Balance]
bs <- [Address] -> m [Balance]
forall (m :: * -> *). StoreReadExtra m => [Address] -> m [Balance]
getBalances (((Word32, Address) -> Address) -> [(Word32, Address)] -> [Address]
forall a b. (a -> b) -> [a] -> [b]
map (Word32, Address) -> Address
forall a b. (a, b) -> b
snd [(Word32, Address)]
as')
                  let xs :: [XPubBal]
xs = [XPubBal] -> [XPubBal]
forall a. [a] -> [a]
reverse ([XPubBal] -> [XPubBal]) -> [XPubBal] -> [XPubBal]
forall a b. (a -> b) -> a -> b
$ (Balance -> Word32 -> XPubBal)
-> [Balance] -> [Word32] -> [XPubBal]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Balance -> Word32 -> XPubBal
xb [Balance]
bs (((Word32, Address) -> Word32) -> [(Word32, Address)] -> [Word32]
forall a b. (a -> b) -> [a] -> [b]
map (Word32, Address) -> Word32
forall a b. (a, b) -> a
fst [(Word32, Address)]
as')
                  [XPubBal] -> [(Word32, Address)] -> m [XPubBal]
go ([XPubBal]
xs [XPubBal] -> [XPubBal] -> [XPubBal]
forall a. Semigroup a => a -> a -> a
<> [XPubBal]
acc) [(Word32, Address)]
as''
         in [XPubBal] -> [(Word32, Address)] -> m [XPubBal]
forall {m :: * -> *}.
StoreReadExtra m =>
[XPubBal] -> [(Word32, Address)] -> m [XPubBal]
go [] [(Word32, Address)]
adrs

  xPubUnspents :: XPubSpec -> [XPubBal] -> Limits -> DatabaseReaderT m [XPubUnspent]
xPubUnspents XPubSpec
_xspec [XPubBal]
xbals Limits
limits = do
    [XPubUnspent]
us <- [[XPubUnspent]] -> [XPubUnspent]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[XPubUnspent]] -> [XPubUnspent])
-> ReaderT DatabaseReader m [[XPubUnspent]]
-> DatabaseReaderT m [XPubUnspent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (XPubBal -> DatabaseReaderT m [XPubUnspent])
-> [XPubBal] -> ReaderT DatabaseReader m [[XPubUnspent]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM XPubBal -> DatabaseReaderT m [XPubUnspent]
forall {f :: * -> *} {r} {r}.
(StoreReadExtra f, HasField "path" r [Word32],
 HasField "balance" r r, HasField "address" r Address) =>
r -> f [XPubUnspent]
h [XPubBal]
cs
    (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall (m :: * -> *) a.
MonadReader DatabaseReader m =>
(DataMetrics -> m a) -> m ()
withMetrics ((DataMetrics -> ReaderT DatabaseReader m ())
 -> ReaderT DatabaseReader m ())
-> (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall a b. (a -> b) -> a -> b
$ \DataMetrics
s -> StatCounter -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *). MonadIO m => StatCounter -> Int -> m ()
incrementCounter DataMetrics
s.dataXPubUnspents ([XPubUnspent] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [XPubUnspent]
us)
    [XPubUnspent] -> DatabaseReaderT m [XPubUnspent]
forall a. a -> ReaderT DatabaseReader m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([XPubUnspent] -> DatabaseReaderT m [XPubUnspent])
-> ([XPubUnspent] -> [XPubUnspent])
-> [XPubUnspent]
-> DatabaseReaderT m [XPubUnspent]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Limits -> [XPubUnspent] -> [XPubUnspent]
forall a. Limits -> [a] -> [a]
applyLimits Limits
limits ([XPubUnspent] -> DatabaseReaderT m [XPubUnspent])
-> [XPubUnspent] -> DatabaseReaderT m [XPubUnspent]
forall a b. (a -> b) -> a -> b
$ (XPubUnspent -> Down XPubUnspent) -> [XPubUnspent] -> [XPubUnspent]
forall b a. Ord b => (a -> b) -> [a] -> [a]
sortOn XPubUnspent -> Down XPubUnspent
forall a. a -> Down a
Down [XPubUnspent]
us
    where
      l :: Limits
l = Limits -> Limits
deOffset Limits
limits
      cs :: [XPubBal]
cs = (XPubBal -> Bool) -> [XPubBal] -> [XPubBal]
forall a. (a -> Bool) -> [a] -> [a]
filter ((UnixTime -> UnixTime -> Bool
forall a. Ord a => a -> a -> Bool
> UnixTime
0) (UnixTime -> Bool) -> (XPubBal -> UnixTime) -> XPubBal -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (.balance.utxo)) [XPubBal]
xbals
      i :: r -> m [Unspent]
i r
b = Address -> Limits -> m [Unspent]
forall (m :: * -> *).
StoreReadExtra m =>
Address -> Limits -> m [Unspent]
getAddressUnspents r
b.balance.address Limits
l
      f :: r -> Unspent -> XPubUnspent
f r
b Unspent
t = XPubUnspent {$sel:path:XPubUnspent :: [Word32]
path = r
b.path, $sel:unspent:XPubUnspent :: Unspent
unspent = Unspent
t}
      h :: r -> f [XPubUnspent]
h r
b = (Unspent -> XPubUnspent) -> [Unspent] -> [XPubUnspent]
forall a b. (a -> b) -> [a] -> [b]
map (r -> Unspent -> XPubUnspent
forall {r}.
HasField "path" r [Word32] =>
r -> Unspent -> XPubUnspent
f r
b) ([Unspent] -> [XPubUnspent]) -> f [Unspent] -> f [XPubUnspent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> r -> f [Unspent]
forall {m :: * -> *} {r} {r}.
(StoreReadExtra m, HasField "balance" r r,
 HasField "address" r Address) =>
r -> m [Unspent]
i r
b

  xPubTxs :: XPubSpec -> [XPubBal] -> Limits -> DatabaseReaderT m [TxRef]
xPubTxs XPubSpec
_xspec [XPubBal]
xbals Limits
limits = do
    let as :: [Address]
as =
          (Balance -> Address) -> [Balance] -> [Address]
forall a b. (a -> b) -> [a] -> [b]
map (.address) ([Balance] -> [Address]) -> [Balance] -> [Address]
forall a b. (a -> b) -> a -> b
$
            (Balance -> Bool) -> [Balance] -> [Balance]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (Balance -> Bool) -> Balance -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Balance -> Bool
nullBalance) ([Balance] -> [Balance]) -> [Balance] -> [Balance]
forall a b. (a -> b) -> a -> b
$
              (XPubBal -> Balance) -> [XPubBal] -> [Balance]
forall a b. (a -> b) -> [a] -> [b]
map (.balance) [XPubBal]
xbals
    [TxRef]
txs <- [Address] -> Limits -> DatabaseReaderT m [TxRef]
forall (m :: * -> *).
StoreReadExtra m =>
[Address] -> Limits -> m [TxRef]
getAddressesTxs [Address]
as Limits
limits
    (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall (m :: * -> *) a.
MonadReader DatabaseReader m =>
(DataMetrics -> m a) -> m ()
withMetrics ((DataMetrics -> ReaderT DatabaseReader m ())
 -> ReaderT DatabaseReader m ())
-> (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall a b. (a -> b) -> a -> b
$ \DataMetrics
s -> StatCounter -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *). MonadIO m => StatCounter -> Int -> m ()
incrementCounter DataMetrics
s.dataXPubTxs ([TxRef] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [TxRef]
txs)
    [TxRef] -> DatabaseReaderT m [TxRef]
forall a. a -> ReaderT DatabaseReader m a
forall (m :: * -> *) a. Monad m => a -> m a
return [TxRef]
txs

  xPubTxCount :: XPubSpec -> [XPubBal] -> DatabaseReaderT m Word32
xPubTxCount XPubSpec
xspec [XPubBal]
xbals = do
    (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall (m :: * -> *) a.
MonadReader DatabaseReader m =>
(DataMetrics -> m a) -> m ()
withMetrics ((DataMetrics -> ReaderT DatabaseReader m ())
 -> ReaderT DatabaseReader m ())
-> (DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall a b. (a -> b) -> a -> b
$ \DataMetrics
s -> StatCounter -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *). MonadIO m => StatCounter -> Int -> m ()
incrementCounter DataMetrics
s.dataXPubTxCount Int
1
    Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word32) -> ([TxRef] -> Int) -> [TxRef] -> Word32
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [TxRef] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([TxRef] -> Word32)
-> DatabaseReaderT m [TxRef] -> DatabaseReaderT m Word32
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> XPubSpec -> [XPubBal] -> Limits -> DatabaseReaderT m [TxRef]
forall (m :: * -> *).
StoreReadExtra m =>
XPubSpec -> [XPubBal] -> Limits -> m [TxRef]
xPubTxs XPubSpec
xspec [XPubBal]
xbals Limits
forall a. Default a => a
def