module Data.Bitcoin.PaymentChannel.Internal.Bitcoin.LockTime where import Data.Word (Word32) import qualified Data.Serialize as Bin import Data.Serialize.Put (putWord32le) import Data.Serialize.Get (getWord32le) import Data.Time.Clock import Data.Time.Clock.POSIX import Data.Typeable import Data.Time.Format () -- instance Show UTCTime -- |Data type representing a Bitcoin LockTime, which specifies a point in time. -- Derive a 'BitcoinLockTime' from a 'Data.Time.Clock.UTCTime' using 'fromDate'. data BitcoinLockTime = -- |A value of "n" represents the point in time at which Bitcoin block number "n" appears LockTimeBlockHeight Word32 | -- |Specifies a point in time using a timestamp with 1-second accuracy LockTimeDate UTCTime deriving (Eq, Ord, Typeable) instance Show BitcoinLockTime where show (LockTimeBlockHeight blockNum) = "block number " ++ show blockNum show (LockTimeDate date) = show date instance Bin.Serialize BitcoinLockTime where put = putWord32le . toWord32 get = parseBitcoinLocktime <$> getWord32le -- | Convert from Bitcoin format ('Word32') parseBitcoinLocktime :: Word32 -> BitcoinLockTime parseBitcoinLocktime i | i < 500000000 = LockTimeBlockHeight i | i >= 500000000 = LockTimeDate $ posixSecondsToUTCTime (fromIntegral i) | otherwise = error "GHC bug?" -- | Convert to Bitcoin format (uint32 UNIX timestamp) toWord32 :: BitcoinLockTime -> Word32 toWord32 (LockTimeBlockHeight i) = i toWord32 (LockTimeDate date) = fromIntegral . round . utcTimeToPOSIXSeconds $ date -- | Convert a 'Data.Time.Clock.UTCTime' to a 'BitcoinLockTime' fromDate :: UTCTime -> BitcoinLockTime fromDate = LockTimeDate usesBlockHeight :: BitcoinLockTime -> Bool usesBlockHeight (LockTimeBlockHeight _) = True usesBlockHeight _ = False