module Bitcoin.Internal.Util
( module Bitcoin.Internal.Util
, module X
, cs
, fmapL
, (<>)
, module Ctrl
)
where
import Bitcoin.Internal.Types as X
import Data.Serialize as Bin
import Data.Serialize.Get as BinGet
import qualified Data.ByteString as B
import qualified Data.Aeson.Types as JSON
import qualified Data.ByteString.Base16 as B16
import qualified Data.ByteString.Char8 as C
import qualified Data.Text as T
import Data.Text.Encoding (decodeUtf8, encodeUtf8)
import Data.Typeable (Typeable, typeOf)
import qualified Network.Haskoin.Crypto as HC
import Data.String.Conversions (cs)
import Data.EitherR (fmapL)
import Data.Monoid ((<>))
import Control.Monad as Ctrl (forM, mapM, (>=>), (<=<))
toInt :: (Integral a, Num b) => a -> b
toInt = fromIntegral
getIndexSafe :: [a] -> Int -> Maybe a
getIndexSafe l i = if i < 0 || i+1 > length l then Nothing else Just $ l !! i
toHexString :: B.ByteString -> String
toHexString = C.unpack . B16.encode
toHexBS :: B.ByteString -> B.ByteString
toHexBS = B16.encode
fromHexBS :: B.ByteString -> B.ByteString
fromHexBS = fst . B16.decode
fromHexString :: String -> B.ByteString
fromHexString hexStr =
case (B16.decode . C.pack) hexStr of
(bs,e) ->
if B.length e /= 0 then B.empty else bs
serialize :: Bin.Serialize a => a -> B.ByteString
serialize = Bin.encode
deserEither :: forall a. (Typeable a, Bin.Serialize a) => B.ByteString -> Either String a
deserEither bs = do
let eitherRes' = BinGet.runGetPartial (Bin.get :: BinGet.Get a) bs
handleResult eitherRes'
where
handleResult eitherRes = case eitherRes of
BinGet.Done val _ -> Right val
BinGet.Partial feedFunc -> handleResult $ feedFunc B.empty
BinGet.Fail e leftoverBS -> Left $
"Type: " ++ show (typeOf (undefined :: a)) ++
". Error: " ++ e ++
". Data consumed (" ++ show offset ++ " bytes): " ++
toHexString (B.take offset bs) ++
". Unconsumed data: (" ++ show ( B.length bs - fromIntegral offset ) ++
" bytes): " ++
toHexString leftoverBS
where offset = B.length bs - B.length leftoverBS
deserHex :: (Typeable a, Bin.Serialize a) => T.Text -> JSON.Parser a
deserHex = either
(fail . ("failed to decode hex: " ++)) return .
deserEither . fromHexBS . encodeUtf8
serHex :: Bin.Serialize a => a -> T.Text
serHex = decodeUtf8 . toHexBS . Bin.encode
mkDummyPubkey :: B.ByteString -> HC.PubKeyC
mkDummyPubkey hexStr =
either (error "mkDummyPubkey: Invalid dummy pubkey data") id (Bin.decode pkBS)
where pkBS = fst $ B16.decode hexStr
mkDummySig :: B.ByteString -> HC.Signature
mkDummySig hexStr =
fromMaybe (error "dummySig: Invalid dummy sig data") (HC.decodeDerSig sigBS)
where sigBS = fst $ B16.decode hexStr
dummySig :: HC.Signature
dummySig = mkDummySig "304402204202cdb61cb702aa62de312a8e5eada817d90c4e26c8b696780b14d1576f204f02203c134d0acb057d917508ca9baab241a4f66ebea32f7acceeaf621a334927e17701"