haskoin-wallet-0.3.0: Network/Haskoin/Wallet/Block.hs
module Network.Haskoin.Wallet.Block where
import Control.Exception (throw)
import Control.Monad.Catch (MonadThrow, throwM)
import Control.Monad.Trans (MonadIO)
import Data.Maybe (fromMaybe)
import Database.Persist.Sql (SqlPersistT)
import Network.Haskoin.Block
import Network.Haskoin.Node.HeaderTree
import Network.Haskoin.Wallet.Model
import Network.Haskoin.Wallet.Transaction
import Network.Haskoin.Wallet.Types
mainChain :: (MonadIO m, MonadThrow m)
=> Either BlockHeight BlockHash
-> ListRequest
-> SqlPersistT m (ListResult NodeBlock)
mainChain blockE ListRequest{..} = do
bestHash <- fst <$> walletBestBlock
bestM <- getBlockByHash bestHash
best <- maybe (throwM $ WalletException "Could not find wallet best block")
return bestM
remoteNode <- case blockE of
Right h -> do
remoteNodeM <- getBlockByHash h
maybe (throwM $ WalletException "Colud not get remote node")
return remoteNodeM
Left h -> do
heightNodeM <- getBlockByHeight best h
maybe (throwM $ WalletException "Could not find bock height")
return heightNodeM
frst <- (+1) . nodeBlockHeight <$> splitBlock best remoteNode
if nodeBlockHeight best < frst
then return $ ListResult [] 0
else do
let cnt = nodeBlockHeight best - frst
limit = min listLimit (cnt - listOffset)
offset =
if listReverse
then cnt - listOffset - limit
else listOffset
nodes <- getBlocksFromHeight best limit (frst + offset)
return $ ListResult nodes cnt
blockTxs :: [NodeBlock] -> [WalletTx] -> [(NodeBlock, [WalletTx])]
blockTxs blocks transactions = reverse $ go [] blocks transactions
where
go bs [] _ = bs
go bs (n:ns) [] = go ((n,[]):bs) ns []
go [] (n:ns) xs = go [(n,[])] ns xs
go (b:bs) (n:ns) (x:xs)
| nodeHash (fst b) == blockHashOf x =
go ((fst b, x : snd b) : bs) (n:ns) xs
| nodeHash n == blockHashOf x =
go ((n, [x]) : b : bs) ns xs
| otherwise = go ((n, []) : b : bs) ns (x:xs)
blockHashOf t = fromMaybe
(throw $ WalletException "Unexpected unconfirmed transaction")
(walletTxConfirmedBy t)