{-| Module : PaymentChannel.Types Copyright : (c) Rune K. Svendsen, 2016 License : PublicDomain Maintainer : runesvend@gmail.com Types used with the interface provided by "PaymentChannel". -} module PaymentChannel.Types ( -- *Shared sender/receiver types/functions FundingTxInfo(..) , ChanParams(..) , PaymentChannel(..), PayChan , PaymentChannelRecv(..) , SharedSecret, HasSharedSecret(..), fromHash, toHash , fundingAddress , clientChangeAddress , getFundingAmount -- *Sender , ClientPayChanI(..) -- *Receiver , ServerPayChan, ServerPayChanG(rpcMetadata) , PayChanStatus(..), MetadataI(..), OpenError(..) , S.getChannelStatus, S.setChannelStatus , S.markAsBusy, S.isReadyForPayment , ServerSettings(..), Hour(..) -- *Receiver state (with pubkey metadata) , ServerPayChanX , S.mkExtendedKeyRPC --, S.metaKeyIndex -- , KeyDeriveIndex -- , mkKeyIndex, word32Index -- *Payment , SignedPayment -- *Receiver settlement , ClosedServerChanI, ClosedServerChan, ClosedServerChanX , getClosedState, cscClosingPayment , SettleTx -- **Error , PayChanError(..), IsPayChanError(..) -- *Bitcoin , module X , module Bitcoin.Fee , PaymentValueSpec(..) , Capped(..) -- *Crypto , SendPubKey(..),RecvPubKey(..),IsPubKey(..),HasSendPubKey(..),HasRecvPubKey(..) -- *Util , module Bitcoin.SpendCond.Util , fromDate , getChanState , clientChangeVal , toHaskoinTx ) where import PaymentChannel.Internal.Types import PaymentChannel.Internal.Receiver.Types import PaymentChannel.Internal.Metadata.Util import PaymentChannel.Internal.Serialization () import PaymentChannel.Internal.Class.Value (HasValue(..)) import PaymentChannel.Internal.Receiver.Open (OpenError(..)) import Bitcoin.SpendCond.Util import Bitcoin.Types as X hiding (fromDate, KeyDeriveIndex, mkKeyIndex, word32Index) import qualified PaymentChannel.Internal.Receiver.Util as S import qualified PaymentChannel.Internal.ChanScript as Script import PaymentChannel.Internal.Error import Bitcoin.Fee import qualified Network.Haskoin.Crypto as HC -- |Both sender and receiver state objects have a 'PaymentChannelState' class HasSignedPayChanState a where getChanState :: a -> PayChanState BtcSig instance HasSignedPayChanState ClientPayChan where getChanState = spcState instance HasSignedPayChanState (ServerPayChanI s) where getChanState = rpcState class HasPayChanState a where getPayChanState :: a -> PayChanState () instance HasPayChanState (ClientPayChanI a) where getPayChanState = mapSigData (const ()) . spcState instance HasPayChanState (ServerPayChanG kd a) where getPayChanState = mapSigData (const ()) . rpcState getFundingAmount :: HasPayChanState a => a -> BtcAmount getFundingAmount = fundingValue . pcsPayment . getPayChanState fundingAddress :: HasPayChanState a => a -> HC.Address fundingAddress = Script.getP2SHFundingAddress . pairRedeemScript . pcsPayment . getPayChanState clientChangeAddress :: HasPayChanState a => a -> HC.Address clientChangeAddress = clientChangeAddr . pcsPayment . getPayChanState -- |Get various information about an open payment channel. class HasSignedPayChanState a => PaymentChannel a where -- |Get amount received by receiver/left for sender valueToMe :: a -> BtcAmount -- |Remaining channel value channelValueLeft :: a -> BtcAmount -- |For internal use getStatePayment :: a -> SignedPayment instance PaymentChannel ClientPayChan where valueToMe = clientChangeVal . pcsPayment . spcState channelValueLeft = valueToMe getStatePayment = pcsPayment . spcState instance PaymentChannel (ServerPayChanI s) where valueToMe (MkServerPayChan s _) = valueOf s channelValueLeft = clientChangeVal . getStatePayment getStatePayment = pcsPayment . rpcState -- |Payment channel state objects with metadata information class PaymentChannel a => PaymentChannelRecv a where -- |Get total amount (both settled and unsettled) sent by client clientTotalValueSent :: a -> BtcAmount instance PaymentChannelRecv (ServerPayChanI (MetadataI a)) where clientTotalValueSent = metaTotalValXfer . rpcMetadata class HasSharedSecret a where getSecret :: a -> SharedSecret instance HasSharedSecret (PayChanState a) where getSecret = pcsSecret instance HasSharedSecret (ServerPayChanG sd s) where getSecret = getSecret . rpcState instance HasSharedSecret ClientPayChan where getSecret = getSecret . spcState -- |Short-hand class PaymentChannel a => PayChan a instance HasFee fee => HasFee (Capped fee) where absoluteFee availVal size (Capped fee) = min availVal desiredFee where desiredFee = absoluteFee availVal size fee -- | Capped/non-capped amount-specifications (get value) class PaymentValueSpec val where paymentValue :: BtcAmount -- ^ Available value -> ServerSettings -> val -- ^ Payment value spec -> BtcAmount -- ^ Actual payment amount ---- | Capped/non-capped amount-specifications (make return type) --class PaymentValueSpec val => PaymentValueRet val ret | ret -> val where -- mkReturnVal :: Tagged val BtcAmount -- ^ Actual payment amount -- -> Either BtcError SignedPayment -- ^ createPayment return value -- -> ret -- ^ 'val'-specific return type newtype Capped val = Capped val instance PaymentValueSpec BtcAmount where paymentValue _ = const id instance PaymentValueSpec (Capped BtcAmount) where paymentValue valueAvailable ServerSettings{..} (Capped amt) = if amt >= valueAvailable then valueAvailable else min amt (valueAvailable - serverConfDustLimit)