module Data.Bitcoin.PaymentChannel.Internal.Bitcoin.Amount where
import qualified Data.Serialize as Ser
import qualified Data.Serialize.Put as SerPut
import qualified Data.Serialize.Get as SerGet
import Data.Word
newtype BitcoinAmount = BitcoinAmount Integer
deriving (Eq, Ord)
instance Show BitcoinAmount where
show amount = show (toInteger amount) ++ " satoshi"
instance Num BitcoinAmount where
(BitcoinAmount a1) * (BitcoinAmount a2) = BitcoinAmount (fromIntegral . capToWord64 $ a1*a2)
(BitcoinAmount a1) + (BitcoinAmount a2) = BitcoinAmount (fromIntegral . capToWord64 $ a1+a2)
(BitcoinAmount a1) (BitcoinAmount a2) = BitcoinAmount (fromIntegral . capToWord64 $ a1a2)
abs = id
signum (BitcoinAmount 0) = BitcoinAmount 0
signum (BitcoinAmount _) = BitcoinAmount 1
fromInteger = BitcoinAmount . fromIntegral . capToWord64
instance Enum BitcoinAmount where
toEnum = BitcoinAmount . fromIntegral . capToWord64 . fromIntegral
fromEnum (BitcoinAmount amount) = fromIntegral amount
instance Real BitcoinAmount where
toRational (BitcoinAmount amount) = toRational amount
instance Integral BitcoinAmount where
toInteger (BitcoinAmount int) = int
quotRem (BitcoinAmount _) (BitcoinAmount _) =
error "Division of two BitcoinAmounts is undefined"
capToWord64 :: Integer -> Word64
capToWord64 i = fromIntegral $
max 0 cappedValue
where
cappedValue = min i $ fromIntegral (maxBound :: Word64)
instance Ser.Serialize BitcoinAmount where
put = SerPut.putWord64le . fromIntegral . toInteger
get = BitcoinAmount . fromIntegral <$> SerGet.getWord64le