module RBPCP.Types
(
module RBPCP.Types
, JsonHex(..)
)
where
import RBPCP.Internal.Types
import RBPCP.Internal.Util
import RBPCP.Internal.Orphans ()
import Data.Aeson
import Data.Aeson.Types
import Data.Word (Word8, Word32, Word64)
import qualified Data.Serialize as Bin
import Data.List (stripPrefix)
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import qualified Data.Text as T
import Data.Function ((&))
type Vout = Word32
type Hours = Word
type BtcConf = Word
data ChannelStatus = ChannelOpen | ChannelClosed deriving (Show, Eq)
instance FromJSON ChannelStatus where
parseJSON = withText "ChannelStatus" $
\s -> case s of
"open" -> return ChannelOpen
"closed" -> return ChannelClosed
e -> fail $ "expected \"open\" or \"closed\", not: " ++ show (cs e :: String)
instance ToJSON ChannelStatus where
toJSON ChannelOpen = String "open"
toJSON ChannelClosed = String "closed"
instance Bin.Serialize ChannelStatus where
put ChannelOpen = Bin.putWord8 0x01
put ChannelClosed = Bin.putWord8 0x02
get = Bin.getWord8 >>= \w -> case w of
0x01 -> return ChannelOpen
0x02 -> return ChannelClosed
n -> fail $ "expected 1 or 2, not: " ++ show n
data ErrorType = PaymentError | ApplicationError deriving (Show, Eq)
instance FromJSON ErrorType where
parseJSON = withText "ErrorType" $
\s -> case s of
"payment_error" -> return PaymentError
"application_error" -> return ApplicationError
e -> fail $ "expected \"payment_error\"" ++
" or \"application_error\", not: " ++ show (cs e :: String)
instance ToJSON ErrorType where
toJSON PaymentError = String "payment_error"
toJSON ApplicationError = String "application_error"
instance Bin.Serialize ErrorType where
put PaymentError = Bin.putWord8 0x01
put ApplicationError = Bin.putWord8 0x02
get = Bin.getWord8 >>= \w -> case w of
0x01 -> return PaymentError
0x02 -> return ApplicationError
n -> fail $ "expected 0x01 or 0x02, not: " ++ show n
data PaymentResult = PaymentResult
{ paymentResult_channel_status :: ChannelStatus
, paymentResult_channel_valueLeft :: Word64
, paymentResult_value_received :: Word64
, paymentResult_settlement_txid :: Maybe TxHash
, paymentResult_application_data :: T.Text
} deriving (Show, Eq, Generic)
data FundingInfo = FundingInfo
{ fundingInfoServerPubkey :: Server PubKey
, fundingInfoDustLimit :: Word64
, fundingInfoFundingAddressCopy :: Address
, fundingInfoRedeem_scriptCopy :: JsonHex Script
, fundingInfoOpenPrice :: Word64
, fundingInfoFunding_tx_min_conf :: BtcConf
, fundingInfoSettlement_period_hours :: Hours
, fundingInfoMin_duration_hours :: Hours
} deriving (Show, Eq, Generic)
data Error = Error
{ errorType :: ErrorType
, errorMessage :: Text
} deriving (Show, Eq, Generic)
data PaymentData = PaymentData
{ paymentDataRedeemScript :: JsonHex Script
, paymentDataFundingTxid :: TxHash
, paymentDataFundingVout :: Vout
, paymentDataSignatureData :: JsonHex Signature
, paymentDataChangeValue :: Word64
, paymentDataChangeAddress :: Address
, paymentDataSighashFlag :: JsonHex SigHash
} deriving (Show, Eq, Generic)
instance FromJSON PaymentData where
parseJSON = genericParseJSON (removeFieldLabelPrefix True "paymentData")
instance ToJSON PaymentData where
toJSON = genericToJSON (removeFieldLabelPrefix False "paymentData")
data Payment = Payment
{ paymentPaymentData :: PaymentData
, paymentApplicationData :: Text
} deriving (Show, Eq, Generic)
instance FromJSON Payment where
parseJSON = genericParseJSON (removeFieldLabelPrefix True "payment")
instance ToJSON Payment where
toJSON = genericToJSON (removeFieldLabelPrefix False "payment")
data ChannelLocation = ChannelLocation
{ channelInfo_channel_uri :: Text
} deriving (Show, Eq, Generic)
instance FromJSON Error where
parseJSON = genericParseJSON (removeFieldLabelPrefix True "error")
instance ToJSON Error where
toJSON = genericToJSON (removeFieldLabelPrefix False "error")
instance FromJSON FundingInfo where
parseJSON = genericParseJSON (removeFieldLabelPrefix True "fundingInfo")
instance ToJSON FundingInfo where
toJSON = genericToJSON (removeFieldLabelPrefix False "fundingInfo")
instance FromJSON PaymentResult where
parseJSON = genericParseJSON (removeFieldLabelPrefix True "paymentResult_")
instance ToJSON PaymentResult where
toJSON = genericToJSON (removeFieldLabelPrefix False "paymentResult_")
removeFieldLabelPrefix :: Bool -> String -> Options
removeFieldLabelPrefix forParsing prefix =
defaultOptions
{ fieldLabelModifier = camelTo2 '_' . fromMaybe (error ("did not find prefix " ++ prefix)) . stripPrefix prefix . replaceSpecialChars
}
where
replaceSpecialChars field = foldl (&) field (map mkCharReplacement specialChars)
specialChars = [("@", "'At"), ("!", "'Exclamation"), ("<=", "'Less_Than_Or_Equal_To"), ("#", "'Hash"), ("$", "'Dollar"), ("%", "'Percent"), ("&", "'Ampersand"), ("*", "'Star"), ("+", "'Plus"), ("-", "'Dash"), (".", "'Period"), (":", "'Colon"), ("|", "'Pipe"), ("<", "'LessThan"), ("!=", "'Not_Equal"), ("=", "'Equal"), ("^", "'Caret"), (">", "'GreaterThan"), ("_", "'Underscore"), (">=", "'Greater_Than_Or_Equal_To")]
mkCharReplacement (replaceStr, searchStr) = T.unpack . replacer (T.pack searchStr) (T.pack replaceStr) . T.pack
replacer = if forParsing then flip T.replace else T.replace
instance FromJSON ChannelLocation where
parseJSON = genericParseJSON (removeFieldLabelPrefix True "channelInfo_")
instance ToJSON ChannelLocation where
toJSON = genericToJSON (removeFieldLabelPrefix False "channelInfo_")