packages feed

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

module PaymentChannel.Internal.Receiver.Util
(
  module PaymentChannel.Internal.Receiver.Util
, module PaymentChannel.Internal.Receiver.Types
, module PaymentChannel.Internal.Class.Value
)
where

import PaymentChannel.Internal.Class.Value
import PaymentChannel.Internal.Receiver.Types
import qualified PaymentChannel.Internal.Settlement.Util as Settle
import PaymentChannel.Internal.Error
import PaymentChannel.Internal.Payment
import PaymentChannel.Internal.Metadata.Util
import PaymentChannel.Internal.Class.Value     (HasValue(..))
import qualified Network.Haskoin.Crypto as HC



-- KeyDeriveIndex

-- |Create a 'ServerPayChanX', which has an associated BIP32 key index, from a
--  'ServerPayChan'
mkExtendedKeyRPC :: ServerPayChanI a -> HC.XPubKey -> Maybe ServerPayChanX
mkExtendedKeyRPC rpc@(MkServerPayChan pcs _) xpk =
    -- Check that it's the right pubkey first
    if xPubKey xpk == getPubKey (getRecvPubKey pcs) then
            Just $ mkExtendedKeyRPCUnsafe (fromIntegral $ HC.xPubIndex xpk) rpc
        else
            Nothing

mkExtendedKeyRPCUnsafe :: Word32 -> ServerPayChanI a -> ServerPayChanX
mkExtendedKeyRPCUnsafe i rpc =
    rpc {
        rpcMetadata =
            Metadata (fromIntegral i) 0 [] (valueOf $ rpcState rpc) ReadyForPayment
        }

mkDummyExtendedRPC :: ServerPayChanI a -> ServerPayChanX
mkDummyExtendedRPC = mkExtendedKeyRPCUnsafe 0

metaKeyIndex :: ServerPayChanI KeyDeriveIndex -> KeyDeriveIndex
metaKeyIndex = mdKeyData . rpcMetadata


-- Status
setChannelStatus :: PayChanStatus -> ServerPayChanI a -> ServerPayChanI a
setChannelStatus s pcs@MkServerPayChan{ rpcMetadata = meta } =
    pcs { rpcMetadata = metaSetStatus s meta }

getChannelStatus :: ServerPayChanI a -> PayChanStatus
getChannelStatus MkServerPayChan{ rpcMetadata = meta } =
    metaGetStatus meta

markAsBusy :: ServerPayChanI a -> ServerPayChanI a
markAsBusy = setChannelStatus PaymentInProgress

isReadyForPayment :: ServerPayChanI a -> Bool
isReadyForPayment =
    (== ReadyForPayment) . getChannelStatus

checkChannelStatus :: ServerPayChanI a -> Either PayChanError (ServerPayChanI a)
checkChannelStatus rpc =
    maybe
    (Right rpc)
    (Left . StatusError)
    (checkReadyForPayment $ getChannelStatus rpc)


-- Metadata
calcNewData :: MetadataI a -> PayChanState BtcSig -> MetadataI a
calcNewData md@Metadata{ mdUnsettledValue = oldValRecvd, mdPayCount = oldCount } pcs =
    md { mdUnsettledValue = checkedVal, mdPayCount = oldCount+1 }
    where checkedVal  = if newValRecvd < oldValRecvd then error "BUG: Value lost :(" else newValRecvd
          newValRecvd = valueOf pcs

updateMetadata :: ServerPayChanI a -> ServerPayChanI a
updateMetadata rpc@MkServerPayChan{..} =
    rpc { rpcMetadata = calcNewData rpcMetadata rpcState }