packages feed

bitcoin-payment-channel-1.0.0.0: src/PaymentChannel/Internal/Util.hs

{-# LANGUAGE ScopedTypeVariables #-}

module PaymentChannel.Internal.Util
(
    module PaymentChannel.Internal.Util
-- ,   module Bitcoin.Util
-- ,   module Bitcoin.LockTime.Types
,   module Bin, module BinGet, module BinPut
,   module JSON, module JSONT, module JSONUtil
,   module Sci
,   module Data.Maybe
,   module Data.Either
,   B.ByteString
,   Generic
,   Typeable
,   Int64
,   module Tagged
,   cs
,   fmapL
,   (<>)
,   module Ctrl
)
where

import PaymentChannel.Internal.Serialization.JSON as JSONUtil


import Data.Serialize       as Bin
import Data.Serialize.Get   as BinGet
import Data.Serialize.Put   as BinPut
import Data.Aeson           as JSON hiding (Result(..), encode, decode)
import Data.Aeson.Types     as JSONT hiding (Result(..))
import Data.Scientific      as Sci

import           Data.Monoid                    ((<>))
import           Data.Maybe
import           Data.Either
import           Data.Tagged                    as Tagged hiding (witness)
import qualified Data.ByteString.Base16         as B16
import qualified Data.ByteString                as B
import qualified Data.ByteString.Char8          as C
import qualified Data.Text                      as T
import qualified Data.Aeson.Types               as JSON
import           Data.Int                   (Int64)
import           Data.String.Conversions    (cs)
import           Data.Text.Encoding         (decodeUtf8, encodeUtf8)
import           Data.EitherR               (fmapL)
import           Control.Monad              as Ctrl (forM, mapM, (>=>), (<=<))
import           GHC.Generics               (Generic)
import           Data.Typeable              (Typeable, typeOf)
import qualified Network.Haskoin.Crypto     as HC

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


-- dummyPubkey :: HC.PubKeyC
-- dummyPubkey = mkDummyPubkey "0323dcd0a7481cb90e3583923701b14d0b6757ebd76bf5b49e696c61f193d7a489"

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 = mkDummySig "304402204202cdb61cb702aa62de312a8e5eada817d90c4e26c8b696780b14d1576f204f02203c134d0acb057d917508ca9baab241a4f66ebea32f7acceeaf621a334927e17701"