{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}

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

import Conduit
  ( ConduitT,
    dropC,
    dropWhileC,
    lift,
    mapC,
    runConduit,
    sinkList,
    takeC,
    (.|),
  )
import Control.Monad.Except (runExceptT, throwError)
import Control.Monad.Reader (ReaderT, ask, asks, runReaderT)
import Data.Bits ((.&.))
import qualified Data.ByteString as BS
import Data.Default (def)
import Data.Function (on)
import Data.List (sortOn)
import Data.Maybe (fromMaybe)
import Data.Ord (Down (..))
import Data.Serialize (encode)
import Data.Word (Word32, Word64)
import Database.RocksDB
  ( ColumnFamily,
    Config (..),
    DB (..),
    Iterator,
    withDBCF,
    withIterCF,
  )
import Database.RocksDB.Query
  ( insert,
    matching,
    matchingAsListCF,
    matchingSkip,
    retrieve,
    retrieveCF,
  )
import Haskoin
  ( Address,
    BlockHash,
    BlockHeight,
    Network,
    OutPoint (..),
    TxHash,
    pubSubKey,
    txHash,
  )
import Haskoin.Store.Common
import Haskoin.Store.Data
import Haskoin.Store.Database.Types
import qualified System.Metrics as Metrics
import System.Metrics.Counter (Counter)
import qualified System.Metrics.Counter as Counter
import UnliftIO (MonadIO, MonadUnliftIO, liftIO)

type DatabaseReaderT = ReaderT DatabaseReader

data DatabaseReader = DatabaseReader
  { DatabaseReader -> DB
databaseHandle :: !DB,
    DatabaseReader -> Word32
databaseMaxGap :: !Word32,
    DatabaseReader -> Word32
databaseInitialGap :: !Word32,
    DatabaseReader -> Network
databaseNetwork :: !Network,
    DatabaseReader -> Maybe DataMetrics
databaseMetrics :: !(Maybe DataMetrics)
  }

incrementCounter ::
  MonadIO m =>
  (DataMetrics -> Counter) ->
  Int ->
  ReaderT DatabaseReader m ()
incrementCounter :: (DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
incrementCounter DataMetrics -> Counter
f Int
i =
  (DatabaseReader -> Maybe DataMetrics)
-> ReaderT DatabaseReader m (Maybe DataMetrics)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks DatabaseReader -> Maybe DataMetrics
databaseMetrics ReaderT DatabaseReader m (Maybe DataMetrics)
-> (Maybe DataMetrics -> ReaderT DatabaseReader m ())
-> ReaderT DatabaseReader m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    Just DataMetrics
s -> IO () -> ReaderT DatabaseReader m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ReaderT DatabaseReader m ())
-> IO () -> ReaderT DatabaseReader m ()
forall a b. (a -> b) -> a -> b
$ Counter -> Int64 -> IO ()
Counter.add (DataMetrics -> Counter
f DataMetrics
s) (Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
i)
    Maybe DataMetrics
Nothing -> () -> ReaderT DatabaseReader m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

dataVersion :: Word32
dataVersion :: Word32
dataVersion = Word32
17

withDatabaseReader ::
  MonadUnliftIO m =>
  Network ->
  Word32 ->
  Word32 ->
  FilePath ->
  Maybe DataMetrics ->
  DatabaseReaderT m a ->
  m a
withDatabaseReader :: Network
-> Word32
-> Word32
-> FilePath
-> Maybe DataMetrics
-> DatabaseReaderT m a
-> m a
withDatabaseReader Network
net Word32
igap Word32
gap FilePath
dir Maybe DataMetrics
stats DatabaseReaderT m a
f =
  FilePath -> Config -> [(FilePath, Config)] -> (DB -> m a) -> m a
forall (m :: * -> *) a.
MonadUnliftIO m =>
FilePath -> Config -> [(FilePath, Config)] -> (DB -> m a) -> m a
withDBCF FilePath
dir Config
cfg [(FilePath, 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 :: DB
-> Word32
-> Word32
-> Network
-> Maybe DataMetrics
-> DatabaseReader
DatabaseReader
            { databaseHandle :: DB
databaseHandle = DB
db,
              databaseMaxGap :: Word32
databaseMaxGap = Word32
gap,
              databaseNetwork :: Network
databaseNetwork = Network
net,
              databaseInitialGap :: Word32
databaseInitialGap = Word32
igap,
              databaseMetrics :: Maybe DataMetrics
databaseMetrics = Maybe DataMetrics
stats
            }
    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 :: Bool
createIfMissing = Bool
True, maxFiles :: Maybe Int
maxFiles = Int -> Maybe Int
forall a. a -> Maybe a
Just (-Int
1)}

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

addrTxCF :: DB -> ColumnFamily
addrTxCF :: DB -> ColumnFamily
addrTxCF = [ColumnFamily] -> ColumnFamily
forall a. [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. [a] -> Int -> a
!! Int
1

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

spenderCF :: DB -> ColumnFamily
spenderCF :: DB -> ColumnFamily
spenderCF DB
db = DB -> [ColumnFamily]
columnFamilies DB
db [ColumnFamily] -> Int -> ColumnFamily
forall a. [a] -> Int -> a
!! Int
3

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

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

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

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

initRocksDB :: MonadIO m => DatabaseReader -> m ()
initRocksDB :: DatabaseReader -> m ()
initRocksDB DatabaseReader {databaseHandle :: DatabaseReader -> DB
databaseHandle = DB
db} = do
  Either FilePath ()
e <-
    ExceptT FilePath m () -> m (Either FilePath ())
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT (ExceptT FilePath m () -> m (Either FilePath ()))
-> ExceptT FilePath m () -> m (Either FilePath ())
forall a b. (a -> b) -> a -> b
$
      DB -> VersionKey -> ExceptT FilePath 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 FilePath m (Maybe Word32)
-> (Maybe Word32 -> ExceptT FilePath m ()) -> ExceptT FilePath m ()
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 FilePath m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
          | Bool
otherwise -> FilePath -> ExceptT FilePath m ()
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError FilePath
"Incorrect RocksDB database version"
        Maybe Word32
Nothing -> DB -> ExceptT FilePath m ()
forall (m :: * -> *). MonadIO m => DB -> m ()
setInitRocksDB DB
db
  case Either FilePath ()
e of
    Left FilePath
s -> FilePath -> m ()
forall a. HasCallStack => FilePath -> a
error FilePath
s
    Right () -> () -> m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

setInitRocksDB :: MonadIO m => DB -> m ()
setInitRocksDB :: 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 :: 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) ()
-> ConduitM (AddrTxKey, ()) TxRef (DatabaseReaderT m) ()
-> ConduitT i TxRef (DatabaseReaderT m) ()
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| ((AddrTxKey, ()) -> TxRef)
-> ConduitM (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 (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 (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
          Just TxData {txDataBlock :: TxData -> BlockRef
txDataBlock = 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 {txDataBlock :: TxData -> BlockRef
txDataBlock = MemRef {}} ->
            let cond :: AddrTxKey -> Bool
cond (AddrTxKey Address
_a (TxRef MemRef {} TxHash
th)) =
                  TxHash
th TxHash -> TxHash -> Bool
forall a. Eq a => a -> a -> Bool
/= TxHash
txh
                cond (AddrTxKey Address
_a (TxRef BlockRef {} TxHash
_th)) =
                  Bool
False
             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) ()
-> ConduitM (AddrTxKey, ()) (AddrTxKey, ()) (DatabaseReaderT m) ()
-> ConduitT i (AddrTxKey, ()) (DatabaseReaderT m) ()
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| (((AddrTxKey, ()) -> Bool)
-> ConduitM (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) ConduitM (AddrTxKey, ()) (AddrTxKey, ()) (DatabaseReaderT m) ()
-> ConduitM (AddrTxKey, ()) (AddrTxKey, ()) (DatabaseReaderT m) ()
-> ConduitM (AddrTxKey, ()) (AddrTxKey, ()) (DatabaseReaderT m) ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ((AddrTxKey, ()) -> (AddrTxKey, ()))
-> ConduitM (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 (m :: * -> *) a. Monad m => a -> m a
return ()

unspentConduit ::
  MonadUnliftIO m =>
  Address ->
  Maybe Start ->
  Iterator ->
  ConduitT i Unspent (DatabaseReaderT m) ()
unspentConduit :: Address
-> Maybe Start
-> Iterator
-> ConduitT i Unspent (DatabaseReaderT m) ()
unspentConduit 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) ()
-> ConduitM (AddrOutKey, OutVal) Unspent (DatabaseReaderT m) ()
-> ConduitT i Unspent (DatabaseReaderT m) ()
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| ((AddrOutKey, OutVal) -> Unspent)
-> ConduitM (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 AddrOutKey -> OutVal -> Unspent
toUnspent)
  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 (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 (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
          Just TxData {txDataBlock :: TxData -> BlockRef
txDataBlock = 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 {txDataBlock :: TxData -> BlockRef
txDataBlock = MemRef {}} ->
            let cond :: AddrOutKey -> Bool
cond (AddrOutKey Address
_a MemRef {} OutPoint
p) =
                  OutPoint -> TxHash
outPointHash OutPoint
p TxHash -> TxHash -> Bool
forall a. Eq a => a -> a -> Bool
/= TxHash
txh
                cond (AddrOutKey Address
_a BlockRef {} OutPoint
_p) =
                  Bool
False
             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) ()
-> ConduitM
     (AddrOutKey, OutVal) (AddrOutKey, OutVal) (DatabaseReaderT m) ()
-> ConduitT i (AddrOutKey, OutVal) (DatabaseReaderT m) ()
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| (((AddrOutKey, OutVal) -> Bool)
-> ConduitM
     (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) ConduitM
  (AddrOutKey, OutVal) (AddrOutKey, OutVal) (DatabaseReaderT m) ()
-> ConduitM
     (AddrOutKey, OutVal) (AddrOutKey, OutVal) (DatabaseReaderT m) ()
-> ConduitM
     (AddrOutKey, OutVal) (AddrOutKey, OutVal) (DatabaseReaderT m) ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ((AddrOutKey, OutVal) -> (AddrOutKey, OutVal))
-> ConduitM
     (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 (m :: * -> *) a. Monad m => a -> m a
return ()

withManyIters ::
  MonadUnliftIO m =>
  DB ->
  ColumnFamily ->
  Int ->
  ([Iterator] -> m a) ->
  m a
withManyIters :: DB -> ColumnFamily -> Int -> ([Iterator] -> m a) -> m a
withManyIters DB
db ColumnFamily
cf Int
i [Iterator] -> m a
f = [Iterator] -> Int -> m a
forall t. (Eq t, Num t) => [Iterator] -> t -> m a
go [] Int
i
  where
    go :: [Iterator] -> t -> m a
go [Iterator]
acc t
0 = [Iterator] -> m a
f [Iterator]
acc
    go [Iterator]
acc t
n = DB -> ColumnFamily -> (Iterator -> m a) -> m a
forall (m :: * -> *) a.
MonadUnliftIO m =>
DB -> ColumnFamily -> (Iterator -> m a) -> m a
withIterCF DB
db ColumnFamily
cf ((Iterator -> m a) -> m a) -> (Iterator -> m a) -> m a
forall a b. (a -> b) -> a -> b
$ \Iterator
it -> [Iterator] -> t -> 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 :: [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 ()
-> ConduitM o Void m [o] -> ConduitT () Void m [o]
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM 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 () -> ConduitM o Void m [o] -> ConduitM o Void m [o]
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| ConduitM o Void m [o]
forall (m :: * -> *) a o. Monad m => ConduitT a o m [a]
sinkList

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

  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 DatabaseReader -> DB
databaseHandle
    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 (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
      Maybe TxData
Nothing -> Maybe TxData -> DatabaseReaderT m (Maybe TxData)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe TxData
forall a. Maybe a
Nothing
      Just TxData
t -> do
        (DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *).
MonadIO m =>
(DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
incrementCounter DataMetrics -> Counter
dataTxCount Int
1
        Maybe TxData -> DatabaseReaderT m (Maybe TxData)
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 = do
    DB
db <- (DatabaseReader -> DB) -> ReaderT DatabaseReader m DB
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks DatabaseReader -> DB
databaseHandle
    DB
-> ColumnFamily -> SpenderKey -> DatabaseReaderT m (Maybe Spender)
forall (m :: * -> *) key value.
(MonadIO m, KeyValue key value, Serialize key, Serialize value) =>
DB -> ColumnFamily -> key -> m (Maybe value)
retrieveCF DB
db (DB -> ColumnFamily
spenderCF DB
db) (OutPoint -> SpenderKey
SpenderKey OutPoint
op) DatabaseReaderT m (Maybe Spender)
-> (Maybe Spender -> DatabaseReaderT m (Maybe Spender))
-> DatabaseReaderT m (Maybe Spender)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
      Maybe Spender
Nothing -> Maybe Spender -> DatabaseReaderT m (Maybe Spender)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Spender
forall a. Maybe a
Nothing
      Just Spender
s -> do
        (DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *).
MonadIO m =>
(DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
incrementCounter DataMetrics -> Counter
dataSpenderCount Int
1
        Maybe Spender -> DatabaseReaderT m (Maybe Spender)
forall (m :: * -> *) a. Monad m => a -> m a
return (Spender -> Maybe Spender
forall a. a -> Maybe a
Just Spender
s)

  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 DatabaseReader -> DB
databaseHandle
    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 (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (OutPoint -> UnspentVal -> Unspent
valToUnspent OutPoint
p) Maybe UnspentVal
val of
      Maybe Unspent
Nothing -> Maybe Unspent -> DatabaseReaderT m (Maybe Unspent)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Unspent
forall a. Maybe a
Nothing
      Just Unspent
u -> do
        (DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *).
MonadIO m =>
(DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
incrementCounter DataMetrics -> Counter
dataUnspentCount Int
1
        Maybe Unspent -> DatabaseReaderT m (Maybe Unspent)
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 DatabaseReader -> DB
databaseHandle
    (DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *).
MonadIO m =>
(DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
incrementCounter DataMetrics -> Counter
dataBalanceCount Int
1
    (BalVal -> Balance) -> Maybe BalVal -> Maybe Balance
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 DatabaseReader -> DB
databaseHandle
    (DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *).
MonadIO m =>
(DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
incrementCounter DataMetrics -> Counter
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 -> Counter) -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *).
MonadIO m =>
(DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
incrementCounter DataMetrics -> Counter
dataBestCount Int
1
    (DatabaseReader -> DB) -> ReaderT DatabaseReader m DB
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks DatabaseReader -> DB
databaseHandle ReaderT DatabaseReader m DB
-> (DB -> DatabaseReaderT m (Maybe BlockHash))
-> DatabaseReaderT m (Maybe BlockHash)
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 DatabaseReader -> DB
databaseHandle
    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 (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
      Maybe [BlockHash]
Nothing -> [BlockHash] -> DatabaseReaderT m [BlockHash]
forall (m :: * -> *) a. Monad m => a -> m a
return []
      Just [BlockHash]
ls -> do
        (DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *).
MonadIO m =>
(DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
incrementCounter DataMetrics -> Counter
dataBlockCount ([BlockHash] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [BlockHash]
ls)
        [BlockHash] -> DatabaseReaderT m [BlockHash]
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 DatabaseReader -> DB
databaseHandle
    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 (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
      Maybe BlockData
Nothing -> Maybe BlockData -> DatabaseReaderT m (Maybe BlockData)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe BlockData
forall a. Maybe a
Nothing
      Just BlockData
b -> do
        (DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *).
MonadIO m =>
(DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
incrementCounter DataMetrics -> Counter
dataBlockCount Int
1
        Maybe BlockData -> DatabaseReaderT m (Maybe BlockData)
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 DatabaseReader -> DB
databaseHandle
    DB
-> ColumnFamily
-> Int
-> ([Iterator] -> DatabaseReaderT m [TxRef])
-> DatabaseReaderT m [TxRef]
forall (m :: * -> *) a.
MonadUnliftIO m =>
DB -> ColumnFamily -> Int -> ([Iterator] -> m a) -> m a
withManyIters DB
db (DB -> ColumnFamily
addrTxCF DB
db) ([Address] -> 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 -> Counter) -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *).
MonadIO m =>
(DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
incrementCounter DataMetrics -> Counter
dataAddrTxCount ([TxRef] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [TxRef]
txs)
      [TxRef] -> DatabaseReaderT m [TxRef]
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. (a -> b) -> [a] -> [b]
map ((Address -> Iterator -> ConduitT i TxRef (DatabaseReaderT m) ())
-> (Address, Iterator) -> ConduitT i TxRef (DatabaseReaderT m) ()
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Address -> Iterator -> ConduitT i TxRef (DatabaseReaderT m) ()
forall (m :: * -> *) i.
MonadUnliftIO m =>
Address -> Iterator -> ConduitT i TxRef (DatabaseReaderT m) ()
c) ([(Address, Iterator)]
 -> [ConduitT i TxRef (DatabaseReaderT m) ()])
-> ([Iterator] -> [(Address, Iterator)])
-> [Iterator]
-> [ConduitT i TxRef (DatabaseReaderT m) ()]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Address] -> [Iterator] -> [(Address, Iterator)]
forall a b. [a] -> [b] -> [(a, b)]
zip [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 -> Maybe Start
start Limits
limits)

  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 DatabaseReader -> DB
databaseHandle
    DB
-> ColumnFamily
-> Int
-> ([Iterator] -> DatabaseReaderT m [Unspent])
-> DatabaseReaderT m [Unspent]
forall (m :: * -> *) a.
MonadUnliftIO m =>
DB -> ColumnFamily -> Int -> ([Iterator] -> m a) -> m a
withManyIters DB
db (DB -> ColumnFamily
addrOutCF DB
db) ([Address] -> 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 ([Iterator] -> [ConduitT () Unspent (DatabaseReaderT m) ()]
forall i. [Iterator] -> [ConduitT i Unspent (DatabaseReaderT m) ()]
cs [Iterator]
its) Limits
limits
      (DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *).
MonadIO m =>
(DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
incrementCounter DataMetrics -> Counter
dataUnspentCount ([Unspent] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Unspent]
uns)
      [Unspent] -> DatabaseReaderT m [Unspent]
forall (m :: * -> *) a. Monad m => a -> m a
return [Unspent]
uns
    where
      cs :: [Iterator] -> [ConduitT i Unspent (DatabaseReaderT m) ()]
cs = ((Address, Iterator) -> ConduitT i Unspent (DatabaseReaderT m) ())
-> [(Address, Iterator)]
-> [ConduitT i Unspent (DatabaseReaderT m) ()]
forall a b. (a -> b) -> [a] -> [b]
map ((Address -> Iterator -> ConduitT i Unspent (DatabaseReaderT m) ())
-> (Address, Iterator) -> ConduitT i Unspent (DatabaseReaderT m) ()
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Address -> Iterator -> ConduitT i Unspent (DatabaseReaderT m) ()
forall (m :: * -> *) i.
MonadUnliftIO m =>
Address -> Iterator -> ConduitT i Unspent (DatabaseReaderT m) ()
c) ([(Address, Iterator)]
 -> [ConduitT i Unspent (DatabaseReaderT m) ()])
-> ([Iterator] -> [(Address, Iterator)])
-> [Iterator]
-> [ConduitT i Unspent (DatabaseReaderT m) ()]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Address] -> [Iterator] -> [(Address, Iterator)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Address]
addrs
      c :: Address -> Iterator -> ConduitT i Unspent (DatabaseReaderT m) ()
c Address
a = Address
-> Maybe Start
-> Iterator
-> ConduitT i Unspent (DatabaseReaderT m) ()
forall (m :: * -> *) i.
MonadUnliftIO m =>
Address
-> Maybe Start
-> Iterator
-> ConduitT i Unspent (DatabaseReaderT m) ()
unspentConduit Address
a (Limits -> Maybe Start
start Limits
limits)

  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 DatabaseReader -> DB
databaseHandle
    [Unspent]
us <- DB
-> ColumnFamily
-> (Iterator -> DatabaseReaderT m [Unspent])
-> DatabaseReaderT m [Unspent]
forall (m :: * -> *) a.
MonadUnliftIO m =>
DB -> ColumnFamily -> (Iterator -> m a) -> m a
withIterCF 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
$
        Address
-> Maybe Start
-> Iterator
-> ConduitT () Unspent (DatabaseReaderT m) ()
forall (m :: * -> *) i.
MonadUnliftIO m =>
Address
-> Maybe Start
-> Iterator
-> ConduitT i Unspent (DatabaseReaderT m) ()
unspentConduit Address
a (Limits -> Maybe Start
start Limits
limits) Iterator
it
          ConduitT () Unspent (DatabaseReaderT m) ()
-> ConduitM Unspent Void (DatabaseReaderT m) [Unspent]
-> ConduitT () Void (DatabaseReaderT m) [Unspent]
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM 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) ()
-> ConduitM Unspent Void (DatabaseReaderT m) [Unspent]
-> ConduitM Unspent Void (DatabaseReaderT m) [Unspent]
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| ConduitM Unspent Void (DatabaseReaderT m) [Unspent]
forall (m :: * -> *) a o. Monad m => ConduitT a o m [a]
sinkList
    (DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *).
MonadIO m =>
(DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
incrementCounter DataMetrics -> Counter
dataUnspentCount ([Unspent] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Unspent]
us)
    [Unspent] -> DatabaseReaderT m [Unspent]
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 DatabaseReader -> DB
databaseHandle
    [TxRef]
txs <- DB
-> ColumnFamily
-> (Iterator -> DatabaseReaderT m [TxRef])
-> DatabaseReaderT m [TxRef]
forall (m :: * -> *) a.
MonadUnliftIO m =>
DB -> ColumnFamily -> (Iterator -> m a) -> m a
withIterCF 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 -> Maybe Start
start Limits
limits) Iterator
it
          ConduitT () TxRef (DatabaseReaderT m) ()
-> ConduitM TxRef Void (DatabaseReaderT m) [TxRef]
-> ConduitT () Void (DatabaseReaderT m) [TxRef]
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM 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) ()
-> ConduitM TxRef Void (DatabaseReaderT m) [TxRef]
-> ConduitM TxRef Void (DatabaseReaderT m) [TxRef]
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| ConduitM TxRef Void (DatabaseReaderT m) [TxRef]
forall (m :: * -> *) a o. Monad m => ConduitT a o m [a]
sinkList
    (DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *).
MonadIO m =>
(DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
incrementCounter DataMetrics -> Counter
dataAddrTxCount ([TxRef] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [TxRef]
txs)
    [TxRef] -> DatabaseReaderT m [TxRef]
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 DatabaseReader -> Word32
databaseMaxGap

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

  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 DatabaseReader -> DB
databaseHandle
    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 (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 :: TxData -> Bool
f TxData
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 (TxData -> Tx
txData TxData
t)
              b :: Word8
b = 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
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 -> Counter) -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *).
MonadIO m =>
(DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
incrementCounter DataMetrics -> Counter
dataTxCount ([TxData] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [TxData]
txs)
    [TxData] -> DatabaseReaderT m [TxData]
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)
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
    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 :: * -> *) a.
(StoreReadExtra m, Integral a) =>
a -> 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) (Word32 -> Word32 -> [(Word32, Address)]
aderiv Word32
0 Word32
0))
    if (XPubBal -> Bool) -> [XPubBal] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Balance -> Bool
nullBalance (Balance -> Bool) -> (XPubBal -> Balance) -> XPubBal -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. XPubBal -> Balance
xPubBal) [XPubBal]
ext1
      then do
        (DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *).
MonadIO m =>
(DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
incrementCounter DataMetrics -> Counter
dataXPubBals ([XPubBal] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [XPubBal]
ext1)
        [XPubBal] -> DatabaseReaderT m [XPubBal]
forall (m :: * -> *) a. Monad m => a -> m a
return [XPubBal]
ext1
      else do
        [XPubBal]
ext2 <- Word32
-> Word32 -> [(Word32, Address)] -> DatabaseReaderT m [XPubBal]
forall (m :: * -> *) a.
(StoreReadExtra m, Integral a) =>
a -> Word32 -> [(Word32, Address)] -> m [XPubBal]
derive_until_gap Word32
gap Word32
0 (Word32 -> Word32 -> [(Word32, Address)]
aderiv Word32
0 Word32
igap)
        [XPubBal]
chg <- Word32
-> Word32 -> [(Word32, Address)] -> DatabaseReaderT m [XPubBal]
forall (m :: * -> *) a.
(StoreReadExtra m, Integral a) =>
a -> Word32 -> [(Word32, Address)] -> m [XPubBal]
derive_until_gap Word32
gap Word32
1 (Word32 -> Word32 -> [(Word32, Address)]
aderiv 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 -> Counter) -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *).
MonadIO m =>
(DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
incrementCounter DataMetrics -> Counter
dataXPubBals ([XPubBal] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [XPubBal]
bals)
        [XPubBal] -> DatabaseReaderT m [XPubBal]
forall (m :: * -> *) a. Monad m => a -> m a
return [XPubBal]
bals
    where
      aderiv :: Word32 -> Word32 -> [(Word32, Address)]
aderiv Word32
m =
        DeriveAddr -> XPubKey -> Word32 -> [(Word32, Address)]
deriveAddresses
          (DeriveType -> DeriveAddr
deriveFunction (XPubSpec -> DeriveType
xPubDeriveType XPubSpec
xpub))
          (XPubKey -> Word32 -> XPubKey
pubSubKey (XPubSpec -> XPubKey
xPubSpecKey XPubSpec
xpub) Word32
m)
      xbalance :: Word32 -> Balance -> Word32 -> XPubBal
xbalance Word32
m Balance
b Word32
n = XPubBal :: [Word32] -> Balance -> XPubBal
XPubBal {xPubBalPath :: [Word32]
xPubBalPath = [Word32
m, Word32
n], xPubBal :: Balance
xPubBal = Balance
b}
      derive_until_gap :: a -> Word32 -> [(Word32, Address)] -> m [XPubBal]
derive_until_gap a
_ Word32
_ [] = [XPubBal] -> m [XPubBal]
forall (m :: * -> *) a. Monad m => a -> m a
return []
      derive_until_gap a
gap Word32
m [(Word32, Address)]
as = do
        let ([(Word32, Address)]
as1, [(Word32, Address)]
as2) = Int
-> [(Word32, Address)]
-> ([(Word32, Address)], [(Word32, Address)])
forall a. Int -> [a] -> ([a], [a])
splitAt (a -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
gap) [(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)]
as1)
        let xbs :: [XPubBal]
xbs = (Balance -> Word32 -> XPubBal)
-> [Balance] -> [Word32] -> [XPubBal]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (Word32 -> Balance -> Word32 -> XPubBal
xbalance Word32
m) [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)]
as1)
        if (Balance -> Bool) -> [Balance] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Balance -> Bool
nullBalance [Balance]
bs
          then [XPubBal] -> m [XPubBal]
forall (m :: * -> *) a. Monad m => a -> m a
return [XPubBal]
xbs
          else ([XPubBal]
xbs [XPubBal] -> [XPubBal] -> [XPubBal]
forall a. Semigroup a => a -> a -> a
<>) ([XPubBal] -> [XPubBal]) -> m [XPubBal] -> m [XPubBal]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> Word32 -> [(Word32, Address)] -> m [XPubBal]
derive_until_gap a
gap Word32
m [(Word32, Address)]
as2

  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)
mapM XPubBal -> DatabaseReaderT m [XPubUnspent]
forall (f :: * -> *).
StoreReadExtra f =>
XPubBal -> f [XPubUnspent]
h [XPubBal]
cs
    (DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *).
MonadIO m =>
(DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
incrementCounter DataMetrics -> Counter
dataXPubUnspents ([XPubUnspent] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [XPubUnspent]
us)
    [XPubUnspent] -> DatabaseReaderT m [XPubUnspent]
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 -> UnixTime
balanceUnspentCount (Balance -> UnixTime)
-> (XPubBal -> Balance) -> XPubBal -> UnixTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. XPubBal -> Balance
xPubBal) [XPubBal]
xbals
      i :: XPubBal -> m [Unspent]
i XPubBal
b = do
        [Unspent]
us <- Address -> Limits -> m [Unspent]
forall (m :: * -> *).
StoreReadExtra m =>
Address -> Limits -> m [Unspent]
getAddressUnspents (Balance -> Address
balanceAddress (XPubBal -> Balance
xPubBal XPubBal
b)) Limits
l
        [Unspent] -> m [Unspent]
forall (m :: * -> *) a. Monad m => a -> m a
return [Unspent]
us
      f :: XPubBal -> Unspent -> XPubUnspent
f XPubBal
b Unspent
t = XPubUnspent :: Unspent -> [Word32] -> XPubUnspent
XPubUnspent {xPubUnspentPath :: [Word32]
xPubUnspentPath = XPubBal -> [Word32]
xPubBalPath XPubBal
b, xPubUnspent :: Unspent
xPubUnspent = Unspent
t}
      h :: XPubBal -> f [XPubUnspent]
h XPubBal
b = (Unspent -> XPubUnspent) -> [Unspent] -> [XPubUnspent]
forall a b. (a -> b) -> [a] -> [b]
map (XPubBal -> Unspent -> XPubUnspent
f XPubBal
b) ([Unspent] -> [XPubUnspent]) -> f [Unspent] -> f [XPubUnspent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> XPubBal -> f [Unspent]
forall (m :: * -> *). StoreReadExtra m => XPubBal -> m [Unspent]
i XPubBal
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 Balance -> Address
balanceAddress ([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 XPubBal -> Balance
xPubBal [XPubBal]
xbals
    [TxRef]
txs <- [Address] -> Limits -> DatabaseReaderT m [TxRef]
forall (m :: * -> *).
StoreReadExtra m =>
[Address] -> Limits -> m [TxRef]
getAddressesTxs [Address]
as Limits
limits
    (DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *).
MonadIO m =>
(DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
incrementCounter DataMetrics -> Counter
dataXPubTxs ([TxRef] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [TxRef]
txs)
    [TxRef] -> DatabaseReaderT m [TxRef]
forall (m :: * -> *) a. Monad m => a -> m a
return [TxRef]
txs

  xPubTxCount :: XPubSpec -> [XPubBal] -> DatabaseReaderT m Word32
xPubTxCount XPubSpec
xspec [XPubBal]
xbals = do
    (DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
forall (m :: * -> *).
MonadIO m =>
(DataMetrics -> Counter) -> Int -> ReaderT DatabaseReader m ()
incrementCounter DataMetrics -> Counter
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 (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