{-# LANGUAGE StrictData #-}
{-# OPTIONS_HADDOCK prune #-}

-- | This module exports settings for different Bitcoin networks.
module Bitcoin.Address.Settings
  ( -- * Settings
    Settings(..)
    -- ** PrefixP2PKH
  , PrefixP2PKH(..)
    -- ** PrefixP2SH
  , PrefixP2SH(..)
    -- ** PrefixSegWit
  , PrefixSegWit
  , prefixSegWit
  , unPrefixSegWit
  , prefixSegWitHRP
  ) where

import qualified Codec.Binary.Bech32 as Bech32
import qualified Data.ByteString as B
import qualified Data.ByteString.Builder as BB
import qualified Data.ByteString.Lazy.Char8 as BL8
import qualified Data.Text.Encoding as T
import Data.Word

import Bitcoin.Address.Internal (hush)

--------------------------------------------------------------------------------

-- | Bitcoin network settings
--
-- For examples, see 'Bitcoin.Address.btc' or 'Bitcoin.Address.btcTestnet' in
-- "Bitcoin.Address".
data Settings = Settings
  { Settings -> PrefixP2PKH
settings_prefixP2PKH :: PrefixP2PKH
  , Settings -> PrefixP2SH
settings_prefixP2SH :: PrefixP2SH
  , Settings -> PrefixSegWit
settings_prefixSegWit :: PrefixSegWit
  } deriving (Settings -> Settings -> Bool
(Settings -> Settings -> Bool)
-> (Settings -> Settings -> Bool) -> Eq Settings
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Settings -> Settings -> Bool
$c/= :: Settings -> Settings -> Bool
== :: Settings -> Settings -> Bool
$c== :: Settings -> Settings -> Bool
Eq, Int -> Settings -> ShowS
[Settings] -> ShowS
Settings -> String
(Int -> Settings -> ShowS)
-> (Settings -> String) -> ([Settings] -> ShowS) -> Show Settings
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Settings] -> ShowS
$cshowList :: [Settings] -> ShowS
show :: Settings -> String
$cshow :: Settings -> String
showsPrec :: Int -> Settings -> ShowS
$cshowsPrec :: Int -> Settings -> ShowS
Show)

--------------------------------------------------------------------------------

-- | The byte prefix used in 'P2PKH' addresses.
newtype PrefixP2PKH = PrefixP2PKH { PrefixP2PKH -> Word8
unPrefixP2PKH :: Word8 }
  deriving newtype (PrefixP2PKH -> PrefixP2PKH -> Bool
(PrefixP2PKH -> PrefixP2PKH -> Bool)
-> (PrefixP2PKH -> PrefixP2PKH -> Bool) -> Eq PrefixP2PKH
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PrefixP2PKH -> PrefixP2PKH -> Bool
$c/= :: PrefixP2PKH -> PrefixP2PKH -> Bool
== :: PrefixP2PKH -> PrefixP2PKH -> Bool
$c== :: PrefixP2PKH -> PrefixP2PKH -> Bool
Eq, Eq PrefixP2PKH
Eq PrefixP2PKH =>
(PrefixP2PKH -> PrefixP2PKH -> Ordering)
-> (PrefixP2PKH -> PrefixP2PKH -> Bool)
-> (PrefixP2PKH -> PrefixP2PKH -> Bool)
-> (PrefixP2PKH -> PrefixP2PKH -> Bool)
-> (PrefixP2PKH -> PrefixP2PKH -> Bool)
-> (PrefixP2PKH -> PrefixP2PKH -> PrefixP2PKH)
-> (PrefixP2PKH -> PrefixP2PKH -> PrefixP2PKH)
-> Ord PrefixP2PKH
PrefixP2PKH -> PrefixP2PKH -> Bool
PrefixP2PKH -> PrefixP2PKH -> Ordering
PrefixP2PKH -> PrefixP2PKH -> PrefixP2PKH
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: PrefixP2PKH -> PrefixP2PKH -> PrefixP2PKH
$cmin :: PrefixP2PKH -> PrefixP2PKH -> PrefixP2PKH
max :: PrefixP2PKH -> PrefixP2PKH -> PrefixP2PKH
$cmax :: PrefixP2PKH -> PrefixP2PKH -> PrefixP2PKH
>= :: PrefixP2PKH -> PrefixP2PKH -> Bool
$c>= :: PrefixP2PKH -> PrefixP2PKH -> Bool
> :: PrefixP2PKH -> PrefixP2PKH -> Bool
$c> :: PrefixP2PKH -> PrefixP2PKH -> Bool
<= :: PrefixP2PKH -> PrefixP2PKH -> Bool
$c<= :: PrefixP2PKH -> PrefixP2PKH -> Bool
< :: PrefixP2PKH -> PrefixP2PKH -> Bool
$c< :: PrefixP2PKH -> PrefixP2PKH -> Bool
compare :: PrefixP2PKH -> PrefixP2PKH -> Ordering
$ccompare :: PrefixP2PKH -> PrefixP2PKH -> Ordering
$cp1Ord :: Eq PrefixP2PKH
Ord, Int -> PrefixP2PKH -> ShowS
[PrefixP2PKH] -> ShowS
PrefixP2PKH -> String
(Int -> PrefixP2PKH -> ShowS)
-> (PrefixP2PKH -> String)
-> ([PrefixP2PKH] -> ShowS)
-> Show PrefixP2PKH
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PrefixP2PKH] -> ShowS
$cshowList :: [PrefixP2PKH] -> ShowS
show :: PrefixP2PKH -> String
$cshow :: PrefixP2PKH -> String
showsPrec :: Int -> PrefixP2PKH -> ShowS
$cshowsPrec :: Int -> PrefixP2PKH -> ShowS
Show)

--------------------------------------------------------------------------------

-- | The byte prefix used in 'P2SH' addresses.
newtype PrefixP2SH = PrefixP2SH { PrefixP2SH -> Word8
unPrefixP2SH :: Word8 }
  deriving newtype (PrefixP2SH -> PrefixP2SH -> Bool
(PrefixP2SH -> PrefixP2SH -> Bool)
-> (PrefixP2SH -> PrefixP2SH -> Bool) -> Eq PrefixP2SH
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PrefixP2SH -> PrefixP2SH -> Bool
$c/= :: PrefixP2SH -> PrefixP2SH -> Bool
== :: PrefixP2SH -> PrefixP2SH -> Bool
$c== :: PrefixP2SH -> PrefixP2SH -> Bool
Eq, Eq PrefixP2SH
Eq PrefixP2SH =>
(PrefixP2SH -> PrefixP2SH -> Ordering)
-> (PrefixP2SH -> PrefixP2SH -> Bool)
-> (PrefixP2SH -> PrefixP2SH -> Bool)
-> (PrefixP2SH -> PrefixP2SH -> Bool)
-> (PrefixP2SH -> PrefixP2SH -> Bool)
-> (PrefixP2SH -> PrefixP2SH -> PrefixP2SH)
-> (PrefixP2SH -> PrefixP2SH -> PrefixP2SH)
-> Ord PrefixP2SH
PrefixP2SH -> PrefixP2SH -> Bool
PrefixP2SH -> PrefixP2SH -> Ordering
PrefixP2SH -> PrefixP2SH -> PrefixP2SH
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: PrefixP2SH -> PrefixP2SH -> PrefixP2SH
$cmin :: PrefixP2SH -> PrefixP2SH -> PrefixP2SH
max :: PrefixP2SH -> PrefixP2SH -> PrefixP2SH
$cmax :: PrefixP2SH -> PrefixP2SH -> PrefixP2SH
>= :: PrefixP2SH -> PrefixP2SH -> Bool
$c>= :: PrefixP2SH -> PrefixP2SH -> Bool
> :: PrefixP2SH -> PrefixP2SH -> Bool
$c> :: PrefixP2SH -> PrefixP2SH -> Bool
<= :: PrefixP2SH -> PrefixP2SH -> Bool
$c<= :: PrefixP2SH -> PrefixP2SH -> Bool
< :: PrefixP2SH -> PrefixP2SH -> Bool
$c< :: PrefixP2SH -> PrefixP2SH -> Bool
compare :: PrefixP2SH -> PrefixP2SH -> Ordering
$ccompare :: PrefixP2SH -> PrefixP2SH -> Ordering
$cp1Ord :: Eq PrefixP2SH
Ord, Int -> PrefixP2SH -> ShowS
[PrefixP2SH] -> ShowS
PrefixP2SH -> String
(Int -> PrefixP2SH -> ShowS)
-> (PrefixP2SH -> String)
-> ([PrefixP2SH] -> ShowS)
-> Show PrefixP2SH
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PrefixP2SH] -> ShowS
$cshowList :: [PrefixP2SH] -> ShowS
show :: PrefixP2SH -> String
$cshow :: PrefixP2SH -> String
showsPrec :: Int -> PrefixP2SH -> ShowS
$cshowsPrec :: Int -> PrefixP2SH -> ShowS
Show)

--------------------------------------------------------------------------------

-- | The Human Readable Part of a 'P2WPKH' or 'P2WSH'
-- address (e.g., the “bc” in “bc1…”)
newtype PrefixSegWit = PrefixSegWit Bech32.HumanReadablePart
  deriving newtype (PrefixSegWit -> PrefixSegWit -> Bool
(PrefixSegWit -> PrefixSegWit -> Bool)
-> (PrefixSegWit -> PrefixSegWit -> Bool) -> Eq PrefixSegWit
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PrefixSegWit -> PrefixSegWit -> Bool
$c/= :: PrefixSegWit -> PrefixSegWit -> Bool
== :: PrefixSegWit -> PrefixSegWit -> Bool
$c== :: PrefixSegWit -> PrefixSegWit -> Bool
Eq)

instance Ord PrefixSegWit where
  compare :: PrefixSegWit -> PrefixSegWit -> Ordering
compare a :: PrefixSegWit
a b :: PrefixSegWit
b = ByteString -> ByteString -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (PrefixSegWit -> ByteString
unPrefixSegWit PrefixSegWit
a) (PrefixSegWit -> ByteString
unPrefixSegWit PrefixSegWit
b)

instance Show PrefixSegWit where
  showsPrec :: Int -> PrefixSegWit -> ShowS
showsPrec n :: Int
n p :: PrefixSegWit
p = Bool -> ShowS -> ShowS
showParen (Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> 10) (ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$
    String -> ShowS
showString "PrefixSegWit " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
    String -> ShowS
forall a. Monoid a => a -> a -> a
mappend (ByteString -> String
BL8.unpack (Builder -> ByteString
BB.toLazyByteString
               (ByteString -> Builder
BB.byteStringHex (PrefixSegWit -> ByteString
unPrefixSegWit PrefixSegWit
p))))

prefixSegWitHRP :: PrefixSegWit -> Bech32.HumanReadablePart
prefixSegWitHRP :: PrefixSegWit -> HumanReadablePart
prefixSegWitHRP (PrefixSegWit hrp :: HumanReadablePart
hrp) = HumanReadablePart
hrp

-- | Obtain the Bech32 Human Readable Part inside 'PrefixSegWit'.
unPrefixSegWit :: PrefixSegWit -> B.ByteString
unPrefixSegWit :: PrefixSegWit -> ByteString
unPrefixSegWit (PrefixSegWit hrp :: HumanReadablePart
hrp) =
  Text -> ByteString
T.encodeUtf8 (HumanReadablePart -> Text
Bech32.humanReadablePartToText HumanReadablePart
hrp)

-- | Construct a 'PrefixSegWit' from the Bech32 Human Readable Part.
prefixSegWit :: B.ByteString -> Maybe PrefixSegWit
prefixSegWit :: ByteString -> Maybe PrefixSegWit
prefixSegWit b :: ByteString
b = do
  Text
t <- Either UnicodeException Text -> Maybe Text
forall a b. Either a b -> Maybe b
hush (ByteString -> Either UnicodeException Text
T.decodeUtf8' ByteString
b)
  HumanReadablePart -> PrefixSegWit
PrefixSegWit (HumanReadablePart -> PrefixSegWit)
-> Maybe HumanReadablePart -> Maybe PrefixSegWit
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Either HumanReadablePartError HumanReadablePart
-> Maybe HumanReadablePart
forall a b. Either a b -> Maybe b
hush (Text -> Either HumanReadablePartError HumanReadablePart
Bech32.humanReadablePartFromText Text
t)