haskoin-store 0.26.6 → 0.27.0
raw patch · 4 files changed
+120/−116 lines, 4 filesdep ~haskoin-store-data
Dependency ranges changed: haskoin-store-data
Files
- haskoin-store.cabal +5/−5
- src/Haskoin/Store.hs +2/−0
- src/Haskoin/Store/Cache.hs +70/−46
- src/Haskoin/Store/Web.hs +43/−65
haskoin-store.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 63c2a0e85118148d88a0ddfbd79034b4a4a45715a820cf743c52d55ac164eb35+-- hash: 05cb5cdade7814a9d00229d0a0ad2fb0c69fbde6a4b8660b01ebd6f5be7eed36 name: haskoin-store-version: 0.26.6+version: 0.27.0 synopsis: Storage and index for Bitcoin and Bitcoin Cash description: Store and index Bitcoin or Bitcoin Cash blocks, transactions, balances and unspent outputs. All data is available via REST API in JSON or binary format.@@ -57,7 +57,7 @@ , hashable >=1.3.0.0 , haskoin-core >=0.13.3 , haskoin-node >=0.13.0- , haskoin-store-data ==0.26.6+ , haskoin-store-data ==0.27.0 , hedis >=0.12.13 , http-types >=0.12.3 , monad-logger >=0.3.32@@ -99,7 +99,7 @@ , haskoin-core >=0.13.3 , haskoin-node >=0.13.0 , haskoin-store- , haskoin-store-data ==0.26.6+ , haskoin-store-data ==0.27.0 , monad-logger >=0.3.32 , mtl >=2.2.2 , nqe >=0.6.1@@ -149,7 +149,7 @@ , hashable >=1.3.0.0 , haskoin-core >=0.13.3 , haskoin-node >=0.13.0- , haskoin-store-data ==0.26.6+ , haskoin-store-data ==0.27.0 , hedis >=0.12.13 , hspec >=2.7.1 , http-types >=0.12.3
src/Haskoin/Store.hs view
@@ -15,6 +15,8 @@ , CacheError (..) , withCache , connectRedis+ , isInCache+ , evictFromCache -- * Store Reader , StoreRead (..)
src/Haskoin/Store/Cache.hs view
@@ -21,15 +21,15 @@ , cacheNewBlock , cacheNewTx , cacheWriter- , isXPubCached- , delXPubKeys+ , isInCache+ , evictFromCache ) where import Control.DeepSeq (NFData) import Control.Monad (forM, forM_, forever, unless, void) import Control.Monad.Logger (MonadLoggerIO, logDebugS, logErrorS, logInfoS, logWarnS)-import Control.Monad.Reader (ReaderT (..), asks)+import Control.Monad.Reader (ReaderT (..), ask, asks) import Control.Monad.Trans (lift) import Control.Monad.Trans.Maybe (MaybeT (..), runMaybeT) import Data.Bits (shift, (.&.), (.|.))@@ -84,7 +84,7 @@ bracket, liftIO, throwIO) import UnliftIO.Concurrent (threadDelay) -runRedis :: MonadLoggerIO m => Redis (Either Reply a) -> CacheT m a+runRedis :: MonadLoggerIO m => Redis (Either Reply a) -> CacheX m a runRedis action = asks cacheConn >>= \conn -> liftIO (Redis.runRedis conn action) >>= \case@@ -101,7 +101,8 @@ , cacheChain :: !Chain } -type CacheT = ReaderT CacheConfig+type CacheT = ReaderT (Maybe CacheConfig)+type CacheX = ReaderT CacheConfig data CacheError = RedisError Reply@@ -136,13 +137,22 @@ getAddressUnspents addr start = lift . getAddressUnspents addr start getAddressesUnspents addrs start = lift . getAddressesUnspents addrs start getMempool = lift getMempool- xPubBals = getXPubBalances- xPubUnspents = getXPubUnspents- xPubTxs = getXPubTxs+ xPubBals xpub =+ ask >>= \case+ Nothing -> lift (xPubBals xpub)+ Just cfg -> lift (runReaderT (getXPubBalances xpub) cfg)+ xPubUnspents xpub start offset limit =+ ask >>= \case+ Nothing -> lift (xPubUnspents xpub start offset limit)+ Just cfg -> lift (runReaderT (getXPubUnspents xpub start offset limit) cfg)+ xPubTxs xpub start offset limit =+ ask >>= \case+ Nothing -> lift (xPubTxs xpub start offset limit)+ Just cfg -> lift (runReaderT (getXPubTxs xpub start offset limit) cfg) getMaxGap = lift getMaxGap getInitialGap = lift getInitialGap -withCache :: StoreRead m => CacheConfig -> CacheT m a -> m a+withCache :: StoreRead m => (Maybe CacheConfig) -> CacheT m a -> m a withCache s f = runReaderT f s balancesPfx :: ByteString@@ -160,7 +170,7 @@ -> Maybe BlockRef -> Offset -> Maybe Limit- -> CacheT m [BlockTx]+ -> CacheX m [BlockTx] getXPubTxs xpub start offset limit = do xpubtxt <- xpubText xpub $(logDebugS) "Cache" $ "Getting xpub txs for " <> xpubtxt@@ -183,7 +193,7 @@ else do $(logDebugS) "Cache" $ "Using DB to return txs for xpub " <> xpubtxt- xPubBalsTxs bals start offset limit+ lift $ xPubBalsTxs bals start offset limit getXPubUnspents :: (MonadUnliftIO m, MonadLoggerIO m, StoreRead m)@@ -191,7 +201,7 @@ -> Maybe BlockRef -> Offset -> Maybe Limit- -> CacheT m [XPubUnspent]+ -> CacheX m [XPubUnspent] getXPubUnspents xpub start offset limit = do xpubtxt <- xpubText xpub $(logDebugS) "Cache" $ "Getting utxo for xpub " <> xpubtxt@@ -209,11 +219,11 @@ else do $(logDebugS) "Cache" $ "Using DB to return utxo for xpub " <> xpubtxt- xPubBalsUnspents bals start offset limit+ lift $ xPubBalsUnspents bals start offset limit where process bals = do ops <- map snd <$> cacheGetXPubUnspents xpub start offset limit- uns <- catMaybes <$> mapM getUnspent ops+ uns <- catMaybes <$> lift (mapM getUnspent ops) let addrmap = Map.fromList $ map (\b -> (balanceAddress (xPubBal b), xPubBalPath b)) bals@@ -240,7 +250,7 @@ getXPubBalances :: (MonadUnliftIO m, MonadLoggerIO m, StoreRead m) => XPubSpec- -> CacheT m [XPubBal]+ -> CacheX m [XPubBal] getXPubBalances xpub = do xpubtxt <- xpubText xpub $(logDebugS) "Cache" $ "Getting balances for xpub " <> xpubtxt@@ -255,13 +265,19 @@ $(logDebugS) "Cache" $ "Caching balances for xpub " <> xpubtxt fst <$> newXPubC xpub -isXPubCached :: MonadLoggerIO m => XPubSpec -> CacheT m Bool+isInCache :: MonadLoggerIO m => XPubSpec -> CacheT m Bool+isInCache xpub =+ ask >>= \case+ Nothing -> return False+ Just cfg -> runReaderT (isXPubCached xpub) cfg++isXPubCached :: MonadLoggerIO m => XPubSpec -> CacheX m Bool isXPubCached = runRedis . redisIsXPubCached redisIsXPubCached :: RedisCtx m f => XPubSpec -> m (f Bool) redisIsXPubCached xpub = Redis.exists (balancesPfx <> encode xpub) -cacheGetXPubBalances :: MonadLoggerIO m => XPubSpec -> CacheT m [XPubBal]+cacheGetXPubBalances :: MonadLoggerIO m => XPubSpec -> CacheX m [XPubBal] cacheGetXPubBalances xpub = do bals <- runRedis $ redisGetXPubBalances xpub touchKeys [xpub]@@ -273,7 +289,7 @@ -> Maybe BlockRef -> Offset -> Maybe Limit- -> CacheT m [BlockTx]+ -> CacheX m [BlockTx] cacheGetXPubTxs xpub start offset limit = do txs <- runRedis $ redisGetXPubTxs xpub start offset limit touchKeys [xpub]@@ -285,7 +301,7 @@ -> Maybe BlockRef -> Offset -> Maybe Limit- -> CacheT m [(BlockRef, OutPoint)]+ -> CacheX m [(BlockRef, OutPoint)] cacheGetXPubUnspents xpub start offset limit = do uns <- runRedis $ redisGetXPubUnspents xpub start offset limit touchKeys [xpub]@@ -442,7 +458,7 @@ maxKey :: ByteString maxKey = "max" -isAnythingCached :: MonadLoggerIO m => CacheT m Bool+isAnythingCached :: MonadLoggerIO m => CacheX m Bool isAnythingCached = runRedis $ Redis.exists maxKey xPubAddrFunction :: DeriveType -> XPubKey -> Address@@ -464,7 +480,7 @@ x <- receive inbox cacheWriterReact x -lockIt :: MonadLoggerIO m => ByteString -> CacheT m (Maybe Word32)+lockIt :: MonadLoggerIO m => ByteString -> CacheX m (Maybe Word32) lockIt k = do rnd <- liftIO randomIO go rnd >>= \case@@ -498,7 +514,7 @@ Redis.setOpts k (cs (show rnd)) opts -unlockIt :: MonadLoggerIO m => ByteString -> Maybe Word32 -> CacheT m ()+unlockIt :: MonadLoggerIO m => ByteString -> Maybe Word32 -> CacheX m () unlockIt _ Nothing = return () unlockIt k (Just i) = runRedis (Redis.get k) >>= \case@@ -521,8 +537,8 @@ withLock :: (MonadLoggerIO m, MonadUnliftIO m) => ByteString- -> CacheT m a- -> CacheT m (Maybe a)+ -> CacheX m a+ -> CacheX m (Maybe a) withLock k f = bracket (lockIt k) (unlockIt k) $ \case Just _ -> Just <$> f@@ -531,8 +547,8 @@ withLockWait :: (MonadLoggerIO m, MonadUnliftIO m) => ByteString- -> CacheT m a- -> CacheT m a+ -> CacheX m a+ -> CacheX m a withLockWait k f = do $(logDebugS) "Cache" $ "Acquiring " <> cs k <> " lock…" go@@ -545,7 +561,7 @@ threadDelay r go -pruneDB :: (MonadUnliftIO m, MonadLoggerIO m, StoreRead m) => CacheT m Integer+pruneDB :: (MonadUnliftIO m, MonadLoggerIO m, StoreRead m) => CacheX m Integer pruneDB = do isAnythingCached >>= \case True -> do@@ -568,7 +584,7 @@ "Pruning " <> cs (show (length ks)) <> " old xpubs" delXPubKeys ks -touchKeys :: MonadLoggerIO m => [XPubSpec] -> CacheT m ()+touchKeys :: MonadLoggerIO m => [XPubSpec] -> CacheX m () touchKeys xpubs = do now <- systemSeconds <$> liftIO getSystemTime runRedis $ redisTouchKeys now xpubs@@ -581,7 +597,7 @@ cacheWriterReact :: (MonadUnliftIO m, MonadLoggerIO m, StoreRead m) => CacheWriterMessage- -> CacheT m ()+ -> CacheX m () cacheWriterReact CacheNewBlock = newBlockC cacheWriterReact (CacheNewTx th) = withLockWait importLockKey $ do@@ -604,7 +620,7 @@ newXPubC :: (MonadUnliftIO m, MonadLoggerIO m, StoreRead m) => XPubSpec- -> CacheT m ([XPubBal], Bool)+ -> CacheX m ([XPubBal], Bool) newXPubC xpub = cachePrime >> do bals <- lift $ xPubBals xpub@@ -647,7 +663,7 @@ e <- redisAddXPubTxs xpub xtxs return $ b >> c >> d >> e >> return () -newBlockC :: (MonadUnliftIO m, MonadLoggerIO m, StoreRead m) => CacheT m ()+newBlockC :: (MonadUnliftIO m, MonadLoggerIO m, StoreRead m) => CacheX m () newBlockC = withLockWait importLockKey f where f =@@ -709,7 +725,7 @@ Just newcachenode -> importBlockC (headerHash (nodeHeader newcachenode)) >> f -importBlockC :: (MonadUnliftIO m, StoreRead m, MonadLoggerIO m) => BlockHash -> CacheT m ()+importBlockC :: (MonadUnliftIO m, StoreRead m, MonadLoggerIO m) => BlockHash -> CacheX m () importBlockC bh = lift (getBlock bh) >>= \case Nothing -> do@@ -733,7 +749,7 @@ blockHashToHex bh cacheSetHead bh -removeHeadC :: (StoreRead m, MonadUnliftIO m, MonadLoggerIO m) => CacheT m ()+removeHeadC :: (StoreRead m, MonadUnliftIO m, MonadLoggerIO m) => CacheX m () removeHeadC = void . runMaybeT $ do bh <- MaybeT cacheGetHead@@ -752,7 +768,7 @@ importMultiTxC :: (MonadUnliftIO m, StoreRead m, MonadLoggerIO m) => [TxData]- -> CacheT m ()+ -> CacheX m () importMultiTxC txs = do $(logDebugS) "Cache" $ "Processing " <> cs (show (length txs)) <> " txs…" $(logDebugS) "Cache" $@@ -767,7 +783,7 @@ $(logDebugS) "Cache" $ "Getting unspent data for " <> cs (show (length allops)) <> " outputs…" unspentmap <- getunspents- gap <- getMaxGap+ gap <- lift getMaxGap now <- systemSeconds <$> liftIO getSystemTime let xpubs = allxpubsls addrmap forM_ (zip [(1 :: Int) ..] xpubs) $ \(i, xpub) -> do@@ -894,7 +910,7 @@ cacheAddAddresses :: (StoreRead m, MonadUnliftIO m, MonadLoggerIO m) => [(Address, AddressXPub)]- -> CacheT m ()+ -> CacheX m () cacheAddAddresses [] = $(logDebugS) "Cache" "No further addresses to add" cacheAddAddresses addrs = do $(logDebugS) "Cache" $@@ -916,7 +932,7 @@ let xpubs = HashSet.toList . HashSet.fromList . map addressXPubSpec $ Map.elems amap $(logDebugS) "Cache" $ "Getting xpub balances…" xmap <- getbals xpubs- gap <- getMaxGap+ gap <- lift getMaxGap let notnulls = getnotnull balmap addrs' = getNewAddrs gap xmap notnulls cacheAddAddresses addrs'@@ -964,7 +980,7 @@ Nothing -> [] Just bals -> addrsToAdd gap bals a -syncMempoolC :: (MonadUnliftIO m, MonadLoggerIO m, StoreRead m) => CacheT m ()+syncMempoolC :: (MonadUnliftIO m, MonadLoggerIO m, StoreRead m) => CacheX m () syncMempoolC = do nodepool <- (HashSet.fromList . map blockTxHash) <$> lift getMempool cachepool <- (HashSet.fromList . map blockTxHash) <$> cacheGetMempool@@ -989,15 +1005,15 @@ Nothing -> return (Left th) Just tx -> return (Right tx) -cacheGetMempool :: MonadLoggerIO m => CacheT m [BlockTx]+cacheGetMempool :: MonadLoggerIO m => CacheX m [BlockTx] cacheGetMempool = runRedis redisGetMempool -cacheGetHead :: MonadLoggerIO m => CacheT m (Maybe BlockHash)+cacheGetHead :: MonadLoggerIO m => CacheX m (Maybe BlockHash) cacheGetHead = runRedis redisGetHead cachePrime :: (StoreRead m, MonadUnliftIO m, MonadLoggerIO m)- => CacheT m (Maybe BlockHash)+ => CacheX m (Maybe BlockHash) cachePrime = cacheGetHead >>= \case Nothing -> do@@ -1014,13 +1030,13 @@ return $ a >> b >> return (Just newhead) Just cachehead -> return $ Just cachehead -cacheSetHead :: (MonadLoggerIO m, StoreRead m) => BlockHash -> CacheT m ()+cacheSetHead :: (MonadLoggerIO m, StoreRead m) => BlockHash -> CacheX m () cacheSetHead bh = do $(logDebugS) "Cache" $ "Cache head set to: " <> blockHashToHex bh runRedis (redisSetHead bh) >> return () cacheGetAddrsInfo ::- MonadLoggerIO m => [Address] -> CacheT m [Maybe AddressXPub]+ MonadLoggerIO m => [Address] -> CacheX m [Maybe AddressXPub] cacheGetAddrsInfo as = runRedis (redisGetAddrsInfo as) redisAddToMempool :: (Applicative f, RedisCtx m f) => [BlockTx] -> m (f Integer)@@ -1039,10 +1055,18 @@ (Functor f, RedisCtx m f) => Address -> AddressXPub -> m (f ()) redisSetAddrInfo a i = void <$> Redis.set (addrPfx <> encode a) (encode i) +evictFromCache ::+ (MonadUnliftIO m, MonadLoggerIO m, StoreRead m)+ => [XPubSpec]+ -> CacheT m ()+evictFromCache xpubs = ask >>= \case+ Nothing -> return ()+ Just cfg -> void (runReaderT (delXPubKeys xpubs) cfg)+ delXPubKeys :: (MonadUnliftIO m, MonadLoggerIO m, StoreRead m) => [XPubSpec]- -> CacheT m Integer+ -> CacheX m Integer delXPubKeys [] = return 0 delXPubKeys xpubs = do forM_ xpubs $ \x -> do@@ -1193,9 +1217,9 @@ where f t s = BlockTx {blockTxBlock = scoreBlockRef s, blockTxHash = t} -xpubText :: (MonadUnliftIO m, MonadLoggerIO m, StoreRead m) => XPubSpec -> CacheT m Text+xpubText :: (MonadUnliftIO m, MonadLoggerIO m, StoreRead m) => XPubSpec -> CacheX m Text xpubText xpub = do- net <- getNetwork+ net <- lift getNetwork return . cs $ xPubExport net (xPubSpecKey xpub) cacheNewBlock :: MonadIO m => CacheWriter -> m ()
src/Haskoin/Store/Web.hs view
@@ -18,7 +18,8 @@ import Control.Monad.Logger (MonadLogger, MonadLoggerIO, askLoggerIO, logInfoS, monadLoggerLog)-import Control.Monad.Reader (ReaderT, asks, runReaderT)+import Control.Monad.Reader (ReaderT, asks, local,+ runReaderT) import Control.Monad.Trans (lift) import Control.Monad.Trans.Maybe (MaybeT (..), runMaybeT) import Data.Aeson (Encoding, ToJSON (..))@@ -58,7 +59,8 @@ import Haskoin.Node (Chain, OnlinePeer (..), PeerManager, chainGetBest, managerGetPeers, sendMessage)-import Haskoin.Store.Cache (CacheT, delXPubKeys, withCache)+import Haskoin.Store.Cache (CacheT, evictFromCache,+ withCache) import Haskoin.Store.Common (Limit, Offset, PubExcept (..), StoreEvent (..), StoreRead (..), applyOffset, blockAtOrBefore,@@ -182,56 +184,43 @@ runInWebReader :: MonadIO m- => DatabaseReaderT m a- -> CacheT (DatabaseReaderT m) a+ => CacheT (DatabaseReaderT m) a -> ReaderT WebConfig m a-runInWebReader bf cf = do+runInWebReader f = do bdb <- asks (storeDB . webStore) mc <- asks (storeCache . webStore)- lift $ withDatabaseReader bdb $- case mc of- Nothing -> bf- Just c -> withCache c cf+ lift $ withDatabaseReader bdb (withCache mc f) -runNoCache :: MonadIO m => DatabaseReaderT m a -> WebT m a-runNoCache f = lift $ do- bdb <- asks (storeDB . webStore)- lift $ withDatabaseReader bdb f+runNoCache :: MonadIO m => Bool -> ReaderT WebConfig m a -> ReaderT WebConfig m a+runNoCache False f = f+runNoCache True f =+ local (\s -> s {webStore = (webStore s) {storeCache = Nothing}}) f instance (MonadUnliftIO m, MonadLoggerIO m) => StoreRead (ReaderT WebConfig m) where- getMaxGap = runInWebReader getMaxGap getMaxGap- getInitialGap = runInWebReader getInitialGap getInitialGap- getNetwork = runInWebReader getNetwork getNetwork- getBestBlock = runInWebReader getBestBlock getBestBlock- getBlocksAtHeight height =- runInWebReader (getBlocksAtHeight height) (getBlocksAtHeight height)- getBlock bh = runInWebReader (getBlock bh) (getBlock bh)- getTxData th = runInWebReader (getTxData th) (getTxData th)- getSpender op = runInWebReader (getSpender op) (getSpender op)- getSpenders th = runInWebReader (getSpenders th) (getSpenders th)- getUnspent op = runInWebReader (getUnspent op) (getUnspent op)- getBalance a = runInWebReader (getBalance a) (getBalance a)- getBalances as = runInWebReader (getBalances as) (getBalances as)- getMempool = runInWebReader getMempool getMempool+ getMaxGap = runInWebReader getMaxGap+ getInitialGap = runInWebReader getInitialGap+ getNetwork = runInWebReader getNetwork+ getBestBlock = runInWebReader getBestBlock+ getBlocksAtHeight height = runInWebReader (getBlocksAtHeight height)+ getBlock bh = runInWebReader (getBlock bh)+ getTxData th = runInWebReader (getTxData th)+ getSpender op = runInWebReader (getSpender op)+ getSpenders th = runInWebReader (getSpenders th)+ getUnspent op = runInWebReader (getUnspent op)+ getBalance a = runInWebReader (getBalance a)+ getBalances as = runInWebReader (getBalances as)+ getMempool = runInWebReader getMempool getAddressesTxs addrs start limit =- runInWebReader- (getAddressesTxs addrs start limit)- (getAddressesTxs addrs start limit)+ runInWebReader (getAddressesTxs addrs start limit) getAddressesUnspents addrs start limit =- runInWebReader- (getAddressesUnspents addrs start limit)- (getAddressesUnspents addrs start limit)- xPubBals xpub = runInWebReader (xPubBals xpub) (xPubBals xpub)- xPubSummary xpub = runInWebReader (xPubSummary xpub) (xPubSummary xpub)+ runInWebReader (getAddressesUnspents addrs start limit)+ xPubBals xpub = runInWebReader (xPubBals xpub)+ xPubSummary xpub = runInWebReader (xPubSummary xpub) xPubUnspents xpub start offset limit =- runInWebReader- (xPubUnspents xpub start offset limit)- (xPubUnspents xpub start offset limit)+ runInWebReader (xPubUnspents xpub start offset limit) xPubTxs xpub start offset limit =- runInWebReader- (xPubTxs xpub start offset limit)- (xPubTxs xpub start offset limit)+ runInWebReader (xPubTxs xpub start offset limit) instance (MonadUnliftIO m, MonadLoggerIO m) => StoreRead (WebT m) where getNetwork = lift getNetwork@@ -583,9 +572,7 @@ proto <- setupBin res <- filter (not . nullBalance . xPubBal) <$>- if nocache- then runNoCache (xPubBals xpub)- else xPubBals xpub+ lift (runNoCache nocache (xPubBals xpub)) protoSerialNet proto (list . xPubBalToEncoding) res scottyXpubTxs :: (MonadUnliftIO m, MonadLoggerIO m) => Bool -> WebT m ()@@ -597,27 +584,23 @@ limit <- getLimit full o <- getOffset proto <- setupBin- txs <- xPubTxs xpub start o limit+ txs <- lift . runNoCache nocache $ xPubTxs xpub start o limit if full then do txs' <-- catMaybes <$>- if nocache- then runNoCache (mapM (getTransaction . blockTxHash) txs)- else mapM (getTransaction . blockTxHash) txs+ fmap catMaybes . lift . runNoCache nocache $+ mapM (getTransaction . blockTxHash) txs protoSerialNet proto (list . transactionToEncoding) txs' else protoSerial proto txs scottyXpubEvict :: (MonadUnliftIO m, MonadLoggerIO m) => WebT m () scottyXpubEvict =- lift (asks (storeCache . webStore)) >>= \case- Nothing -> S.raise ThingNotFound- Just cache -> do- setHeaders- xpub <- parseXpub- proto <- setupBin- n <- lift $ withCache cache (delXPubKeys [xpub])- protoSerial proto (GenericResult (n > 0))+ lift (asks (storeCache . webStore)) >>= \cache -> do+ setHeaders+ xpub <- parseXpub+ proto <- setupBin+ lift . withCache cache $ evictFromCache [xpub]+ protoSerial proto (GenericResult True) scottyXpubUnspents :: (MonadUnliftIO m, MonadLoggerIO m) => WebT m ()@@ -627,11 +610,9 @@ xpub <- parseXpub proto <- setupBin start <- getStart+ o <- getOffset limit <- getLimit False- uns <-- if nocache- then runNoCache (xPubUnspents xpub start 0 limit)- else xPubUnspents xpub start 0 limit+ uns <- lift . runNoCache nocache $ xPubUnspents xpub start o limit protoSerialNet proto (list . xPubUnspentToEncoding) uns scottyXpubSummary :: (MonadUnliftIO m, MonadLoggerIO m) => WebT m ()@@ -640,10 +621,7 @@ nocache <- parseNoCache xpub <- parseXpub proto <- setupBin- res <-- if nocache- then runNoCache (xPubSummary xpub)- else xPubSummary xpub+ res <- lift . runNoCache nocache $ xPubSummary xpub protoSerial proto res scottyPostTx ::