module Data.Bitcoin.Types ( TransactionId , BlockHash , PrivateKey , Address , Account , Btc , VarInt (..) ) where import Control.Applicative ((<$>)) import Data.Word ( Word64 ) import Data.Binary ( Binary, get, put ) import Data.Binary.Get ( getByteString , getWord8 , getWord16le , getWord32le , getWord64le ) import Data.Binary.Put ( putByteString , putWord8 , putWord16le , putWord32le , putWord64le ) import Data.Fixed import qualified Data.HexString as HS import qualified Data.Base58String.Bitcoin as B58S import qualified Data.Text as T -- | Per Bitcoin documentation, an identifier used to uniquely identify a -- particular transaction; specifically, the sha256d hash of the transaction. type TransactionId = HS.HexString -- | Per Bitcoin document, an identifier used to uniquely identify a block -- by its header. type BlockHash = HS.HexString -- | A base58 private key to sign transactions type PrivateKey = B58S.Base58String -- | Per Bitcoin documentation, an identifier used to uniquely identify a -- particular address. type Address = B58S.Base58String -- | A wallet account can be any easy to remember string. type Account = T.Text -- | The smallest unit of payment possible in Bitcoin is a Satoshi data Satoshi = Satoshi -- | We describe BTC in terms of Satoshi, where one BTC equals 10^8 Satoshis. instance HasResolution Satoshi where resolution _ = 10 ^ ( 8 :: Integer ) -- | A single Bitcoin, which represents 10^8 Satoshis. type Btc = Fixed Satoshi -- | Data type representing a variable length integer. The 'VarInt' type -- usually precedes an array or a string that can vary in length. newtype VarInt = VarInt { getVarInt :: Word64 } deriving (Eq, Show, Read) instance Binary VarInt where get = VarInt <$> ( getWord8 >>= go ) where go 0xff = getWord64le go 0xfe = fromIntegral <$> getWord32le go 0xfd = fromIntegral <$> getWord16le go x = fromIntegral <$> return x put (VarInt x) | x < 0xfd = putWord8 $ fromIntegral x | x <= 0xffff = do putWord8 0xfd putWord16le $ fromIntegral x | x <= 0xffffffff = do putWord8 0xfe putWord32le $ fromIntegral x | otherwise = do putWord8 0xff putWord64le x