{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}

-- | Bcc addresses: payment and stake addresses.
--
module Bcc.Api.Address (
    -- * Payment addresses
    -- | Constructing and inspecting normal payment addresses
    Address(..),

    -- ** Cole addresses
    ColeAddr,
    makeColeAddress,

    -- ** Sophie addresses
    SophieAddr,
    makeSophieAddress,
    PaymentCredential(..),
    StakeAddressReference(..),
    StakeAddressPointer(..),

    -- ** Addresses in any era
    AddressAny(..),

    -- ** Addresses in specific eras
    AddressInEra(..),
    AddressTypeInEra(..),
    coleAddressInEra,
    sophieAddressInEra,
    anyAddressInSophieBasedEra,
    anyAddressInEra,
    toAddressAny,
    makeColeAddressInEra,
    makeSophieAddressInEra,

    -- * Stake addresses
    -- | Constructing and inspecting stake addresses
    StakeAddress(..),
    StakeCredential(..),
    makeStakeAddress,
    StakeKey,
    StakeExtendedKey,

    -- * Internal conversion functions
    toSophieAddr,
    toSophieStakeAddr,
    toSophieStakeCredential,
    fromSophieAddr,
    fromSophiePaymentCredential,
    fromSophieStakeAddr,
    fromSophieStakeCredential,
    fromSophieStakeReference,

    -- * Serialising addresses
    SerialiseAddress(..),

    -- * Data family instances
    AsType(AsColeAddr, AsSophieAddr, AsColeAddress, AsSophieAddress,
           AsAddress, AsAddressAny, AsAddressInEra, AsStakeAddress),

    -- * Helpers
    isKeyAddress
  ) where

import           Prelude

import           Data.Aeson (ToJSON (..))
import qualified Data.Aeson as Aeson
import qualified Data.ByteString.Base58 as Base58
import           Data.Text (Text)
import qualified Data.Text.Encoding as Text

import           Control.Applicative

import           Bcc.Api.Eras
import           Bcc.Api.HasTypeProxy
import           Bcc.Api.Hash
import           Bcc.Api.Key
import           Bcc.Api.KeysCole
import           Bcc.Api.KeysSophie
import           Bcc.Api.NetworkId
import           Bcc.Api.Script
import           Bcc.Api.SerialiseBech32
import           Bcc.Api.SerialiseRaw
import qualified Bcc.Chain.Common as Cole
import qualified Bcc.Ledger.Address as Sophie
import qualified Bcc.Ledger.BaseTypes as Sophie
import qualified Bcc.Ledger.Credential as Sophie
import           Bcc.Ledger.Crypto (StandardCrypto)

-- ----------------------------------------------------------------------------
-- Address Serialisation
--

-- | Address serialisation uses different serialisation formats for different
-- kinds of addresses, so it needs its own class.
--
-- In particular, Cole addresses are typically formatted in base 58, while
-- Sophie addresses (payment and stake) are formatted using Bech32.
--
class HasTypeProxy addr => SerialiseAddress addr where

    serialiseAddress :: addr -> Text

    deserialiseAddress :: AsType addr -> Text -> Maybe addr
    -- TODO: consider adding data AddressDecodeError


-- ----------------------------------------------------------------------------
-- Payment address types
--

-- | A type used as a tag to distinguish Cole addresses.
data ColeAddr

-- | A type used as a tag to distinguish Sophie addresses.
data SophieAddr

instance HasTypeProxy ColeAddr where
    data AsType ColeAddr = AsColeAddr
    proxyToAsType :: Proxy ColeAddr -> AsType ColeAddr
proxyToAsType Proxy ColeAddr
_ = AsType ColeAddr
AsColeAddr

instance HasTypeProxy SophieAddr where
    data AsType SophieAddr = AsSophieAddr
    proxyToAsType :: Proxy SophieAddr -> AsType SophieAddr
proxyToAsType Proxy SophieAddr
_ = AsType SophieAddr
AsSophieAddr


-- ----------------------------------------------------------------------------
-- Payment addresses
--

-- | Addresses are used as locations where assets live. The address determines
-- the rights needed to spend assets at the address: in particular holding some
-- signing key or being able to satisfy the conditions of a script.
--
-- There are currently two types of address:
--
-- * Cole addresses, which use the type tag 'ColeAddr'; and
-- * Sophie addresses, which use the type tag 'SophieAddr'. Notably, Sophie
--   addresses support scripts and stake delegation.
--
-- The /address type/ is subtly from the /ledger era/ in which each
-- address type is valid: while Cole addresses are the only choice in the
-- Cole era, the Sophie era and all subsequent eras support both Cole and
-- Sophie addresses. The 'Address' type param only says the type of the address
-- (either Cole or Sophie). The 'AddressInEra' type connects the address type
-- with the era in which it is supported.
--
data Address addrtype where

     -- | Cole addresses were the only supported address type in the original
     -- Cole era.
     --
     ColeAddress
       :: Cole.Address
       -> Address ColeAddr

     -- | Sophie addresses allow delegation. Sophie addresses were introduced
     -- in Sophie era and are thus supported from the Sophie era onwards
     --
     SophieAddress
       :: Sophie.Network
       -> Sophie.PaymentCredential StandardCrypto
       -> Sophie.StakeReference    StandardCrypto
       -> Address SophieAddr
       -- Note that the two ledger credential types here are parametrised by
       -- the era, but in fact this is a phantom type parameter and they are
       -- the same for all eras. See 'toSophieAddr' below.

deriving instance Eq   (Address addrtype)
deriving instance Ord  (Address addrtype)
deriving instance Show (Address addrtype)


instance HasTypeProxy addrtype => HasTypeProxy (Address addrtype) where
    data AsType (Address addrtype) = AsAddress (AsType addrtype)
    proxyToAsType :: Proxy (Address addrtype) -> AsType (Address addrtype)
proxyToAsType Proxy (Address addrtype)
_ = AsType addrtype -> AsType (Address addrtype)
forall addrtype. AsType addrtype -> AsType (Address addrtype)
AsAddress (Proxy addrtype -> AsType addrtype
forall t. HasTypeProxy t => Proxy t -> AsType t
proxyToAsType (Proxy addrtype
forall k (t :: k). Proxy t
Proxy :: Proxy addrtype))

pattern AsColeAddress :: AsType (Address ColeAddr)
pattern $bAsColeAddress :: AsType (Address ColeAddr)
$mAsColeAddress :: forall r.
AsType (Address ColeAddr) -> (Void# -> r) -> (Void# -> r) -> r
AsColeAddress   = AsAddress AsColeAddr
{-# COMPLETE AsColeAddress #-}

pattern AsSophieAddress :: AsType (Address SophieAddr)
pattern $bAsSophieAddress :: AsType (Address SophieAddr)
$mAsSophieAddress :: forall r.
AsType (Address SophieAddr) -> (Void# -> r) -> (Void# -> r) -> r
AsSophieAddress = AsAddress AsSophieAddr
{-# COMPLETE AsSophieAddress #-}

instance SerialiseAsRawBytes (Address ColeAddr) where
    serialiseToRawBytes :: Address ColeAddr -> ByteString
serialiseToRawBytes (ColeAddress Address
addr) =
        Addr Any -> ByteString
forall crypto. Addr crypto -> ByteString
Sophie.serialiseAddr
      (Addr Any -> ByteString)
-> (Address -> Addr Any) -> Address -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BootstrapAddress Any -> Addr Any
forall crypto. BootstrapAddress crypto -> Addr crypto
Sophie.AddrBootstrap
      (BootstrapAddress Any -> Addr Any)
-> (Address -> BootstrapAddress Any) -> Address -> Addr Any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Address -> BootstrapAddress Any
forall crypto. Address -> BootstrapAddress crypto
Sophie.BootstrapAddress
      (Address -> ByteString) -> Address -> ByteString
forall a b. (a -> b) -> a -> b
$ Address
addr

    deserialiseFromRawBytes :: AsType (Address ColeAddr) -> ByteString -> Maybe (Address ColeAddr)
deserialiseFromRawBytes (AsAddress AsColeAddr) ByteString
bs =
        case ByteString -> Maybe (Addr StandardCrypto)
forall crypto. Crypto crypto => ByteString -> Maybe (Addr crypto)
Sophie.deserialiseAddr ByteString
bs :: Maybe (Sophie.Addr StandardCrypto) of
          Maybe (Addr StandardCrypto)
Nothing             -> Maybe (Address ColeAddr)
forall a. Maybe a
Nothing
          Just Sophie.Addr{} -> Maybe (Address ColeAddr)
forall a. Maybe a
Nothing
          Just (Sophie.AddrBootstrap (Sophie.BootstrapAddress Address
addr)) ->
            Address ColeAddr -> Maybe (Address ColeAddr)
forall a. a -> Maybe a
Just (Address -> Address ColeAddr
ColeAddress Address
addr)

instance SerialiseAsRawBytes (Address SophieAddr) where
    serialiseToRawBytes :: Address SophieAddr -> ByteString
serialiseToRawBytes (SophieAddress Network
nw PaymentCredential StandardCrypto
pc StakeReference StandardCrypto
scr) =
        Addr StandardCrypto -> ByteString
forall crypto. Addr crypto -> ByteString
Sophie.serialiseAddr (Network
-> PaymentCredential StandardCrypto
-> StakeReference StandardCrypto
-> Addr StandardCrypto
forall crypto.
Network
-> PaymentCredential crypto -> StakeReference crypto -> Addr crypto
Sophie.Addr Network
nw PaymentCredential StandardCrypto
pc StakeReference StandardCrypto
scr)

    deserialiseFromRawBytes :: AsType (Address SophieAddr)
-> ByteString -> Maybe (Address SophieAddr)
deserialiseFromRawBytes (AsAddress AsSophieAddr) ByteString
bs =
        case ByteString -> Maybe (Addr StandardCrypto)
forall crypto. Crypto crypto => ByteString -> Maybe (Addr crypto)
Sophie.deserialiseAddr ByteString
bs of
          Maybe (Addr StandardCrypto)
Nothing                       -> Maybe (Address SophieAddr)
forall a. Maybe a
Nothing
          Just Sophie.AddrBootstrap{}  -> Maybe (Address SophieAddr)
forall a. Maybe a
Nothing
          Just (Sophie.Addr Network
nw PaymentCredential StandardCrypto
pc StakeReference StandardCrypto
scr) -> Address SophieAddr -> Maybe (Address SophieAddr)
forall a. a -> Maybe a
Just (Network
-> PaymentCredential StandardCrypto
-> StakeReference StandardCrypto
-> Address SophieAddr
SophieAddress Network
nw PaymentCredential StandardCrypto
pc StakeReference StandardCrypto
scr)

instance SerialiseAsBech32 (Address SophieAddr) where
    bech32PrefixFor :: Address SophieAddr -> Text
bech32PrefixFor (SophieAddress Network
Sophie.Mainnet PaymentCredential StandardCrypto
_ StakeReference StandardCrypto
_) = Text
"addr"
    bech32PrefixFor (SophieAddress Network
Sophie.Testnet PaymentCredential StandardCrypto
_ StakeReference StandardCrypto
_) = Text
"addr_test"

    bech32PrefixesPermitted :: AsType (Address SophieAddr) -> [Text]
bech32PrefixesPermitted (AsAddress AsSophieAddr) = [Text
"addr", Text
"addr_test"]


instance SerialiseAddress (Address ColeAddr) where
    serialiseAddress :: Address ColeAddr -> Text
serialiseAddress addr :: Address ColeAddr
addr@ColeAddress{} =
         ByteString -> Text
Text.decodeLatin1
       (ByteString -> Text)
-> (Address ColeAddr -> ByteString) -> Address ColeAddr -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Alphabet -> ByteString -> ByteString
Base58.encodeBase58 Alphabet
Base58.bitcoinAlphabet
       (ByteString -> ByteString)
-> (Address ColeAddr -> ByteString)
-> Address ColeAddr
-> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Address ColeAddr -> ByteString
forall a. SerialiseAsRawBytes a => a -> ByteString
serialiseToRawBytes
       (Address ColeAddr -> Text) -> Address ColeAddr -> Text
forall a b. (a -> b) -> a -> b
$ Address ColeAddr
addr

    deserialiseAddress :: AsType (Address ColeAddr) -> Text -> Maybe (Address ColeAddr)
deserialiseAddress (AsAddress AsColeAddr) Text
txt = do
      ByteString
bs <- Alphabet -> ByteString -> Maybe ByteString
Base58.decodeBase58 Alphabet
Base58.bitcoinAlphabet (Text -> ByteString
Text.encodeUtf8 Text
txt)
      AsType (Address ColeAddr) -> ByteString -> Maybe (Address ColeAddr)
forall a.
SerialiseAsRawBytes a =>
AsType a -> ByteString -> Maybe a
deserialiseFromRawBytes (AsType ColeAddr -> AsType (Address ColeAddr)
forall addrtype. AsType addrtype -> AsType (Address addrtype)
AsAddress AsType ColeAddr
AsColeAddr) ByteString
bs

instance SerialiseAddress (Address SophieAddr) where
    serialiseAddress :: Address SophieAddr -> Text
serialiseAddress addr :: Address SophieAddr
addr@SophieAddress{} =
      Address SophieAddr -> Text
forall a. SerialiseAsBech32 a => a -> Text
serialiseToBech32 Address SophieAddr
addr

    deserialiseAddress :: AsType (Address SophieAddr) -> Text -> Maybe (Address SophieAddr)
deserialiseAddress (AsAddress AsSophieAddr) Text
t =
      (Bech32DecodeError -> Maybe (Address SophieAddr))
-> (Address SophieAddr -> Maybe (Address SophieAddr))
-> Either Bech32DecodeError (Address SophieAddr)
-> Maybe (Address SophieAddr)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Maybe (Address SophieAddr)
-> Bech32DecodeError -> Maybe (Address SophieAddr)
forall a b. a -> b -> a
const Maybe (Address SophieAddr)
forall a. Maybe a
Nothing) Address SophieAddr -> Maybe (Address SophieAddr)
forall a. a -> Maybe a
Just (Either Bech32DecodeError (Address SophieAddr)
 -> Maybe (Address SophieAddr))
-> Either Bech32DecodeError (Address SophieAddr)
-> Maybe (Address SophieAddr)
forall a b. (a -> b) -> a -> b
$
      AsType (Address SophieAddr)
-> Text -> Either Bech32DecodeError (Address SophieAddr)
forall a.
SerialiseAsBech32 a =>
AsType a -> Text -> Either Bech32DecodeError a
deserialiseFromBech32 (AsType SophieAddr -> AsType (Address SophieAddr)
forall addrtype. AsType addrtype -> AsType (Address addrtype)
AsAddress AsType SophieAddr
AsSophieAddr) Text
t


makeColeAddress :: NetworkId
                 -> VerificationKey ColeKey
                 -> Address ColeAddr
makeColeAddress :: NetworkId -> VerificationKey ColeKey -> Address ColeAddr
makeColeAddress NetworkId
nw (ColeVerificationKey vk) =
    Address -> Address ColeAddr
ColeAddress (Address -> Address ColeAddr) -> Address -> Address ColeAddr
forall a b. (a -> b) -> a -> b
$
      NetworkMagic -> VerificationKey -> Address
Cole.makeVerKeyAddress
        (NetworkId -> NetworkMagic
toColeNetworkMagic NetworkId
nw)
        VerificationKey
vk


makeSophieAddress :: NetworkId
                   -> PaymentCredential
                   -> StakeAddressReference
                   -> Address SophieAddr
makeSophieAddress :: NetworkId
-> PaymentCredential -> StakeAddressReference -> Address SophieAddr
makeSophieAddress NetworkId
nw PaymentCredential
pc StakeAddressReference
scr =
    Network
-> PaymentCredential StandardCrypto
-> StakeReference StandardCrypto
-> Address SophieAddr
SophieAddress
      (NetworkId -> Network
toSophieNetwork NetworkId
nw)
      (PaymentCredential -> PaymentCredential StandardCrypto
toSophiePaymentCredential PaymentCredential
pc)
      (StakeAddressReference -> StakeReference StandardCrypto
toSophieStakeReference StakeAddressReference
scr)


-- ----------------------------------------------------------------------------
-- Either type of address
--

-- | Either a Cole address or a Sophie address.
--
-- Sometimes we need to be able to work with either of the two types of
-- address (Cole or Sophie addresses), but without reference to an era in
-- which the address will be used. This type serves that purpose.
--
data AddressAny = AddressCole   !(Address ColeAddr)
                | AddressSophie !(Address SophieAddr)
  deriving (AddressAny -> AddressAny -> Bool
(AddressAny -> AddressAny -> Bool)
-> (AddressAny -> AddressAny -> Bool) -> Eq AddressAny
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AddressAny -> AddressAny -> Bool
$c/= :: AddressAny -> AddressAny -> Bool
== :: AddressAny -> AddressAny -> Bool
$c== :: AddressAny -> AddressAny -> Bool
Eq, Eq AddressAny
Eq AddressAny
-> (AddressAny -> AddressAny -> Ordering)
-> (AddressAny -> AddressAny -> Bool)
-> (AddressAny -> AddressAny -> Bool)
-> (AddressAny -> AddressAny -> Bool)
-> (AddressAny -> AddressAny -> Bool)
-> (AddressAny -> AddressAny -> AddressAny)
-> (AddressAny -> AddressAny -> AddressAny)
-> Ord AddressAny
AddressAny -> AddressAny -> Bool
AddressAny -> AddressAny -> Ordering
AddressAny -> AddressAny -> AddressAny
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 :: AddressAny -> AddressAny -> AddressAny
$cmin :: AddressAny -> AddressAny -> AddressAny
max :: AddressAny -> AddressAny -> AddressAny
$cmax :: AddressAny -> AddressAny -> AddressAny
>= :: AddressAny -> AddressAny -> Bool
$c>= :: AddressAny -> AddressAny -> Bool
> :: AddressAny -> AddressAny -> Bool
$c> :: AddressAny -> AddressAny -> Bool
<= :: AddressAny -> AddressAny -> Bool
$c<= :: AddressAny -> AddressAny -> Bool
< :: AddressAny -> AddressAny -> Bool
$c< :: AddressAny -> AddressAny -> Bool
compare :: AddressAny -> AddressAny -> Ordering
$ccompare :: AddressAny -> AddressAny -> Ordering
$cp1Ord :: Eq AddressAny
Ord, Int -> AddressAny -> ShowS
[AddressAny] -> ShowS
AddressAny -> String
(Int -> AddressAny -> ShowS)
-> (AddressAny -> String)
-> ([AddressAny] -> ShowS)
-> Show AddressAny
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AddressAny] -> ShowS
$cshowList :: [AddressAny] -> ShowS
show :: AddressAny -> String
$cshow :: AddressAny -> String
showsPrec :: Int -> AddressAny -> ShowS
$cshowsPrec :: Int -> AddressAny -> ShowS
Show)

instance HasTypeProxy AddressAny where
    data AsType AddressAny = AsAddressAny
    proxyToAsType :: Proxy AddressAny -> AsType AddressAny
proxyToAsType Proxy AddressAny
_ = AsType AddressAny
AsAddressAny

instance SerialiseAsRawBytes AddressAny where
    serialiseToRawBytes :: AddressAny -> ByteString
serialiseToRawBytes (AddressCole   Address ColeAddr
addr) = Address ColeAddr -> ByteString
forall a. SerialiseAsRawBytes a => a -> ByteString
serialiseToRawBytes Address ColeAddr
addr
    serialiseToRawBytes (AddressSophie Address SophieAddr
addr) = Address SophieAddr -> ByteString
forall a. SerialiseAsRawBytes a => a -> ByteString
serialiseToRawBytes Address SophieAddr
addr

    deserialiseFromRawBytes :: AsType AddressAny -> ByteString -> Maybe AddressAny
deserialiseFromRawBytes AsType AddressAny
AsAddressAny ByteString
bs =
      case ByteString -> Maybe (Addr StandardCrypto)
forall crypto. Crypto crypto => ByteString -> Maybe (Addr crypto)
Sophie.deserialiseAddr ByteString
bs of
        Maybe (Addr StandardCrypto)
Nothing -> Maybe AddressAny
forall a. Maybe a
Nothing
        Just (Sophie.AddrBootstrap (Sophie.BootstrapAddress Address
addr)) ->
          AddressAny -> Maybe AddressAny
forall a. a -> Maybe a
Just (Address ColeAddr -> AddressAny
AddressCole (Address -> Address ColeAddr
ColeAddress Address
addr))

        Just (Sophie.Addr Network
nw PaymentCredential StandardCrypto
pc StakeReference StandardCrypto
scr) ->
          AddressAny -> Maybe AddressAny
forall a. a -> Maybe a
Just (Address SophieAddr -> AddressAny
AddressSophie (Network
-> PaymentCredential StandardCrypto
-> StakeReference StandardCrypto
-> Address SophieAddr
SophieAddress Network
nw PaymentCredential StandardCrypto
pc StakeReference StandardCrypto
scr))

instance SerialiseAddress AddressAny where
    serialiseAddress :: AddressAny -> Text
serialiseAddress (AddressCole   Address ColeAddr
addr) = Address ColeAddr -> Text
forall addr. SerialiseAddress addr => addr -> Text
serialiseAddress Address ColeAddr
addr
    serialiseAddress (AddressSophie Address SophieAddr
addr) = Address SophieAddr -> Text
forall addr. SerialiseAddress addr => addr -> Text
serialiseAddress Address SophieAddr
addr

    deserialiseAddress :: AsType AddressAny -> Text -> Maybe AddressAny
deserialiseAddress AsType AddressAny
AsAddressAny Text
t =
          (Address ColeAddr -> AddressAny
AddressCole   (Address ColeAddr -> AddressAny)
-> Maybe (Address ColeAddr) -> Maybe AddressAny
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> AsType (Address ColeAddr) -> Text -> Maybe (Address ColeAddr)
forall addr.
SerialiseAddress addr =>
AsType addr -> Text -> Maybe addr
deserialiseAddress (AsType ColeAddr -> AsType (Address ColeAddr)
forall addrtype. AsType addrtype -> AsType (Address addrtype)
AsAddress AsType ColeAddr
AsColeAddr)   Text
t)
      Maybe AddressAny -> Maybe AddressAny -> Maybe AddressAny
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Address SophieAddr -> AddressAny
AddressSophie (Address SophieAddr -> AddressAny)
-> Maybe (Address SophieAddr) -> Maybe AddressAny
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> AsType (Address SophieAddr) -> Text -> Maybe (Address SophieAddr)
forall addr.
SerialiseAddress addr =>
AsType addr -> Text -> Maybe addr
deserialiseAddress (AsType SophieAddr -> AsType (Address SophieAddr)
forall addrtype. AsType addrtype -> AsType (Address addrtype)
AsAddress AsType SophieAddr
AsSophieAddr) Text
t)


-- ----------------------------------------------------------------------------
-- Addresses in the context of a ledger era
--

-- | An 'Address' that can be used in a particular ledger era.
--
-- All current ledger eras support Cole addresses. Sophie addresses are
-- supported in the 'SophieEra' and later eras.
--
data AddressInEra era where
     AddressInEra :: AddressTypeInEra addrtype era
                  -> Address addrtype
                  -> AddressInEra era

instance IsBccEra era => ToJSON (AddressInEra era) where
  toJSON :: AddressInEra era -> Value
toJSON = Text -> Value
Aeson.String (Text -> Value)
-> (AddressInEra era -> Text) -> AddressInEra era -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AddressInEra era -> Text
forall addr. SerialiseAddress addr => addr -> Text
serialiseAddress

instance Eq (AddressInEra era) where
  == :: AddressInEra era -> AddressInEra era -> Bool
(==) (AddressInEra AddressTypeInEra addrtype era
ColeAddressInAnyEra Address addrtype
addr1)
       (AddressInEra AddressTypeInEra addrtype era
ColeAddressInAnyEra Address addrtype
addr2) = Address addrtype
addr1 Address addrtype -> Address addrtype -> Bool
forall a. Eq a => a -> a -> Bool
== Address addrtype
Address addrtype
addr2

  (==) (AddressInEra SophieAddressInEra{} Address addrtype
addr1)
       (AddressInEra SophieAddressInEra{} Address addrtype
addr2) = Address addrtype
addr1 Address addrtype -> Address addrtype -> Bool
forall a. Eq a => a -> a -> Bool
== Address addrtype
Address addrtype
addr2

  (==) (AddressInEra AddressTypeInEra addrtype era
ColeAddressInAnyEra Address addrtype
_)
       (AddressInEra SophieAddressInEra{} Address addrtype
_) = Bool
False

  (==) (AddressInEra SophieAddressInEra{} Address addrtype
_)
       (AddressInEra AddressTypeInEra addrtype era
ColeAddressInAnyEra Address addrtype
_) = Bool
False

deriving instance Show (AddressInEra era)

data AddressTypeInEra addrtype era where

     ColeAddressInAnyEra :: AddressTypeInEra ColeAddr era

     SophieAddressInEra  :: SophieBasedEra era
                          -> AddressTypeInEra SophieAddr era

deriving instance Show (AddressTypeInEra addrtype era)


instance HasTypeProxy era => HasTypeProxy (AddressInEra era) where
    data AsType (AddressInEra era) = AsAddressInEra (AsType era)
    proxyToAsType :: Proxy (AddressInEra era) -> AsType (AddressInEra era)
proxyToAsType Proxy (AddressInEra era)
_ = AsType era -> AsType (AddressInEra era)
forall era. AsType era -> AsType (AddressInEra era)
AsAddressInEra (Proxy era -> AsType era
forall t. HasTypeProxy t => Proxy t -> AsType t
proxyToAsType (Proxy era
forall k (t :: k). Proxy t
Proxy :: Proxy era))

instance IsBccEra era => SerialiseAsRawBytes (AddressInEra era) where

    serialiseToRawBytes :: AddressInEra era -> ByteString
serialiseToRawBytes (AddressInEra AddressTypeInEra addrtype era
ColeAddressInAnyEra Address addrtype
addr) =
      Address addrtype -> ByteString
forall a. SerialiseAsRawBytes a => a -> ByteString
serialiseToRawBytes Address addrtype
addr

    serialiseToRawBytes (AddressInEra SophieAddressInEra{} Address addrtype
addr) =
      Address addrtype -> ByteString
forall a. SerialiseAsRawBytes a => a -> ByteString
serialiseToRawBytes Address addrtype
addr

    deserialiseFromRawBytes :: AsType (AddressInEra era) -> ByteString -> Maybe (AddressInEra era)
deserialiseFromRawBytes AsType (AddressInEra era)
_ ByteString
bs =
      BccEra era -> AddressAny -> Maybe (AddressInEra era)
forall era. BccEra era -> AddressAny -> Maybe (AddressInEra era)
anyAddressInEra BccEra era
forall era. IsBccEra era => BccEra era
bccEra (AddressAny -> Maybe (AddressInEra era))
-> Maybe AddressAny -> Maybe (AddressInEra era)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< AsType AddressAny -> ByteString -> Maybe AddressAny
forall a.
SerialiseAsRawBytes a =>
AsType a -> ByteString -> Maybe a
deserialiseFromRawBytes AsType AddressAny
AsAddressAny ByteString
bs

instance IsBccEra era => SerialiseAddress (AddressInEra era) where
    serialiseAddress :: AddressInEra era -> Text
serialiseAddress (AddressInEra AddressTypeInEra addrtype era
ColeAddressInAnyEra Address addrtype
addr) =
      Address addrtype -> Text
forall addr. SerialiseAddress addr => addr -> Text
serialiseAddress Address addrtype
addr

    serialiseAddress (AddressInEra SophieAddressInEra{} Address addrtype
addr) =
      Address addrtype -> Text
forall addr. SerialiseAddress addr => addr -> Text
serialiseAddress Address addrtype
addr

    deserialiseAddress :: AsType (AddressInEra era) -> Text -> Maybe (AddressInEra era)
deserialiseAddress AsType (AddressInEra era)
_ Text
t =
      BccEra era -> AddressAny -> Maybe (AddressInEra era)
forall era. BccEra era -> AddressAny -> Maybe (AddressInEra era)
anyAddressInEra BccEra era
forall era. IsBccEra era => BccEra era
bccEra (AddressAny -> Maybe (AddressInEra era))
-> Maybe AddressAny -> Maybe (AddressInEra era)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< AsType AddressAny -> Text -> Maybe AddressAny
forall addr.
SerialiseAddress addr =>
AsType addr -> Text -> Maybe addr
deserialiseAddress AsType AddressAny
AsAddressAny Text
t


coleAddressInEra :: Address ColeAddr -> AddressInEra era
coleAddressInEra :: Address ColeAddr -> AddressInEra era
coleAddressInEra = AddressTypeInEra ColeAddr era
-> Address ColeAddr -> AddressInEra era
forall addrtype era.
AddressTypeInEra addrtype era
-> Address addrtype -> AddressInEra era
AddressInEra AddressTypeInEra ColeAddr era
forall era. AddressTypeInEra ColeAddr era
ColeAddressInAnyEra


sophieAddressInEra :: IsSophieBasedEra era
                    => Address SophieAddr -> AddressInEra era
sophieAddressInEra :: Address SophieAddr -> AddressInEra era
sophieAddressInEra = AddressTypeInEra SophieAddr era
-> Address SophieAddr -> AddressInEra era
forall addrtype era.
AddressTypeInEra addrtype era
-> Address addrtype -> AddressInEra era
AddressInEra (SophieBasedEra era -> AddressTypeInEra SophieAddr era
forall era. SophieBasedEra era -> AddressTypeInEra SophieAddr era
SophieAddressInEra SophieBasedEra era
forall era. IsSophieBasedEra era => SophieBasedEra era
sophieBasedEra)


anyAddressInSophieBasedEra :: IsSophieBasedEra era
                            => AddressAny -> AddressInEra era
anyAddressInSophieBasedEra :: AddressAny -> AddressInEra era
anyAddressInSophieBasedEra (AddressCole   Address ColeAddr
addr) = Address ColeAddr -> AddressInEra era
forall era. Address ColeAddr -> AddressInEra era
coleAddressInEra Address ColeAddr
addr
anyAddressInSophieBasedEra (AddressSophie Address SophieAddr
addr) = Address SophieAddr -> AddressInEra era
forall era.
IsSophieBasedEra era =>
Address SophieAddr -> AddressInEra era
sophieAddressInEra Address SophieAddr
addr


anyAddressInEra :: BccEra era
                -> AddressAny
                -> Maybe (AddressInEra era)
anyAddressInEra :: BccEra era -> AddressAny -> Maybe (AddressInEra era)
anyAddressInEra BccEra era
_ (AddressCole Address ColeAddr
addr) =
    AddressInEra era -> Maybe (AddressInEra era)
forall a. a -> Maybe a
Just (AddressTypeInEra ColeAddr era
-> Address ColeAddr -> AddressInEra era
forall addrtype era.
AddressTypeInEra addrtype era
-> Address addrtype -> AddressInEra era
AddressInEra AddressTypeInEra ColeAddr era
forall era. AddressTypeInEra ColeAddr era
ColeAddressInAnyEra Address ColeAddr
addr)

anyAddressInEra BccEra era
era (AddressSophie Address SophieAddr
addr) =
    case BccEra era -> BccEraStyle era
forall era. BccEra era -> BccEraStyle era
bccEraStyle BccEra era
era of
      BccEraStyle era
LegacyColeEra       -> Maybe (AddressInEra era)
forall a. Maybe a
Nothing
      SophieBasedEra SophieBasedEra era
era' -> AddressInEra era -> Maybe (AddressInEra era)
forall a. a -> Maybe a
Just (AddressTypeInEra SophieAddr era
-> Address SophieAddr -> AddressInEra era
forall addrtype era.
AddressTypeInEra addrtype era
-> Address addrtype -> AddressInEra era
AddressInEra (SophieBasedEra era -> AddressTypeInEra SophieAddr era
forall era. SophieBasedEra era -> AddressTypeInEra SophieAddr era
SophieAddressInEra SophieBasedEra era
era') Address SophieAddr
addr)

toAddressAny :: Address addr -> AddressAny
toAddressAny :: Address addr -> AddressAny
toAddressAny a :: Address addr
a@SophieAddress{} = Address SophieAddr -> AddressAny
AddressSophie Address addr
Address SophieAddr
a
toAddressAny a :: Address addr
a@ColeAddress{}   = Address ColeAddr -> AddressAny
AddressCole Address addr
Address ColeAddr
a

makeColeAddressInEra :: NetworkId
                      -> VerificationKey ColeKey
                      -> AddressInEra era
makeColeAddressInEra :: NetworkId -> VerificationKey ColeKey -> AddressInEra era
makeColeAddressInEra NetworkId
nw VerificationKey ColeKey
vk =
    Address ColeAddr -> AddressInEra era
forall era. Address ColeAddr -> AddressInEra era
coleAddressInEra (NetworkId -> VerificationKey ColeKey -> Address ColeAddr
makeColeAddress NetworkId
nw VerificationKey ColeKey
vk)


makeSophieAddressInEra :: IsSophieBasedEra era
                        => NetworkId
                        -> PaymentCredential
                        -> StakeAddressReference
                        -> AddressInEra era
makeSophieAddressInEra :: NetworkId
-> PaymentCredential -> StakeAddressReference -> AddressInEra era
makeSophieAddressInEra NetworkId
nw PaymentCredential
pc StakeAddressReference
scr =
    Address SophieAddr -> AddressInEra era
forall era.
IsSophieBasedEra era =>
Address SophieAddr -> AddressInEra era
sophieAddressInEra (NetworkId
-> PaymentCredential -> StakeAddressReference -> Address SophieAddr
makeSophieAddress NetworkId
nw PaymentCredential
pc StakeAddressReference
scr)


-- ----------------------------------------------------------------------------
-- Stake addresses
--

data StakeAddress where

     StakeAddress
       :: Sophie.Network
       -> Sophie.StakeCredential StandardCrypto
       -> StakeAddress
  deriving (StakeAddress -> StakeAddress -> Bool
(StakeAddress -> StakeAddress -> Bool)
-> (StakeAddress -> StakeAddress -> Bool) -> Eq StakeAddress
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: StakeAddress -> StakeAddress -> Bool
$c/= :: StakeAddress -> StakeAddress -> Bool
== :: StakeAddress -> StakeAddress -> Bool
$c== :: StakeAddress -> StakeAddress -> Bool
Eq, Eq StakeAddress
Eq StakeAddress
-> (StakeAddress -> StakeAddress -> Ordering)
-> (StakeAddress -> StakeAddress -> Bool)
-> (StakeAddress -> StakeAddress -> Bool)
-> (StakeAddress -> StakeAddress -> Bool)
-> (StakeAddress -> StakeAddress -> Bool)
-> (StakeAddress -> StakeAddress -> StakeAddress)
-> (StakeAddress -> StakeAddress -> StakeAddress)
-> Ord StakeAddress
StakeAddress -> StakeAddress -> Bool
StakeAddress -> StakeAddress -> Ordering
StakeAddress -> StakeAddress -> StakeAddress
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 :: StakeAddress -> StakeAddress -> StakeAddress
$cmin :: StakeAddress -> StakeAddress -> StakeAddress
max :: StakeAddress -> StakeAddress -> StakeAddress
$cmax :: StakeAddress -> StakeAddress -> StakeAddress
>= :: StakeAddress -> StakeAddress -> Bool
$c>= :: StakeAddress -> StakeAddress -> Bool
> :: StakeAddress -> StakeAddress -> Bool
$c> :: StakeAddress -> StakeAddress -> Bool
<= :: StakeAddress -> StakeAddress -> Bool
$c<= :: StakeAddress -> StakeAddress -> Bool
< :: StakeAddress -> StakeAddress -> Bool
$c< :: StakeAddress -> StakeAddress -> Bool
compare :: StakeAddress -> StakeAddress -> Ordering
$ccompare :: StakeAddress -> StakeAddress -> Ordering
$cp1Ord :: Eq StakeAddress
Ord, Int -> StakeAddress -> ShowS
[StakeAddress] -> ShowS
StakeAddress -> String
(Int -> StakeAddress -> ShowS)
-> (StakeAddress -> String)
-> ([StakeAddress] -> ShowS)
-> Show StakeAddress
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [StakeAddress] -> ShowS
$cshowList :: [StakeAddress] -> ShowS
show :: StakeAddress -> String
$cshow :: StakeAddress -> String
showsPrec :: Int -> StakeAddress -> ShowS
$cshowsPrec :: Int -> StakeAddress -> ShowS
Show)

data PaymentCredential
       = PaymentCredentialByKey    (Hash PaymentKey)
       | PaymentCredentialByScript  ScriptHash
  deriving (PaymentCredential -> PaymentCredential -> Bool
(PaymentCredential -> PaymentCredential -> Bool)
-> (PaymentCredential -> PaymentCredential -> Bool)
-> Eq PaymentCredential
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PaymentCredential -> PaymentCredential -> Bool
$c/= :: PaymentCredential -> PaymentCredential -> Bool
== :: PaymentCredential -> PaymentCredential -> Bool
$c== :: PaymentCredential -> PaymentCredential -> Bool
Eq, Eq PaymentCredential
Eq PaymentCredential
-> (PaymentCredential -> PaymentCredential -> Ordering)
-> (PaymentCredential -> PaymentCredential -> Bool)
-> (PaymentCredential -> PaymentCredential -> Bool)
-> (PaymentCredential -> PaymentCredential -> Bool)
-> (PaymentCredential -> PaymentCredential -> Bool)
-> (PaymentCredential -> PaymentCredential -> PaymentCredential)
-> (PaymentCredential -> PaymentCredential -> PaymentCredential)
-> Ord PaymentCredential
PaymentCredential -> PaymentCredential -> Bool
PaymentCredential -> PaymentCredential -> Ordering
PaymentCredential -> PaymentCredential -> PaymentCredential
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 :: PaymentCredential -> PaymentCredential -> PaymentCredential
$cmin :: PaymentCredential -> PaymentCredential -> PaymentCredential
max :: PaymentCredential -> PaymentCredential -> PaymentCredential
$cmax :: PaymentCredential -> PaymentCredential -> PaymentCredential
>= :: PaymentCredential -> PaymentCredential -> Bool
$c>= :: PaymentCredential -> PaymentCredential -> Bool
> :: PaymentCredential -> PaymentCredential -> Bool
$c> :: PaymentCredential -> PaymentCredential -> Bool
<= :: PaymentCredential -> PaymentCredential -> Bool
$c<= :: PaymentCredential -> PaymentCredential -> Bool
< :: PaymentCredential -> PaymentCredential -> Bool
$c< :: PaymentCredential -> PaymentCredential -> Bool
compare :: PaymentCredential -> PaymentCredential -> Ordering
$ccompare :: PaymentCredential -> PaymentCredential -> Ordering
$cp1Ord :: Eq PaymentCredential
Ord, Int -> PaymentCredential -> ShowS
[PaymentCredential] -> ShowS
PaymentCredential -> String
(Int -> PaymentCredential -> ShowS)
-> (PaymentCredential -> String)
-> ([PaymentCredential] -> ShowS)
-> Show PaymentCredential
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PaymentCredential] -> ShowS
$cshowList :: [PaymentCredential] -> ShowS
show :: PaymentCredential -> String
$cshow :: PaymentCredential -> String
showsPrec :: Int -> PaymentCredential -> ShowS
$cshowsPrec :: Int -> PaymentCredential -> ShowS
Show)

data StakeCredential
       = StakeCredentialByKey    (Hash StakeKey)
       | StakeCredentialByScript  ScriptHash
  deriving (StakeCredential -> StakeCredential -> Bool
(StakeCredential -> StakeCredential -> Bool)
-> (StakeCredential -> StakeCredential -> Bool)
-> Eq StakeCredential
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: StakeCredential -> StakeCredential -> Bool
$c/= :: StakeCredential -> StakeCredential -> Bool
== :: StakeCredential -> StakeCredential -> Bool
$c== :: StakeCredential -> StakeCredential -> Bool
Eq, Eq StakeCredential
Eq StakeCredential
-> (StakeCredential -> StakeCredential -> Ordering)
-> (StakeCredential -> StakeCredential -> Bool)
-> (StakeCredential -> StakeCredential -> Bool)
-> (StakeCredential -> StakeCredential -> Bool)
-> (StakeCredential -> StakeCredential -> Bool)
-> (StakeCredential -> StakeCredential -> StakeCredential)
-> (StakeCredential -> StakeCredential -> StakeCredential)
-> Ord StakeCredential
StakeCredential -> StakeCredential -> Bool
StakeCredential -> StakeCredential -> Ordering
StakeCredential -> StakeCredential -> StakeCredential
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 :: StakeCredential -> StakeCredential -> StakeCredential
$cmin :: StakeCredential -> StakeCredential -> StakeCredential
max :: StakeCredential -> StakeCredential -> StakeCredential
$cmax :: StakeCredential -> StakeCredential -> StakeCredential
>= :: StakeCredential -> StakeCredential -> Bool
$c>= :: StakeCredential -> StakeCredential -> Bool
> :: StakeCredential -> StakeCredential -> Bool
$c> :: StakeCredential -> StakeCredential -> Bool
<= :: StakeCredential -> StakeCredential -> Bool
$c<= :: StakeCredential -> StakeCredential -> Bool
< :: StakeCredential -> StakeCredential -> Bool
$c< :: StakeCredential -> StakeCredential -> Bool
compare :: StakeCredential -> StakeCredential -> Ordering
$ccompare :: StakeCredential -> StakeCredential -> Ordering
$cp1Ord :: Eq StakeCredential
Ord, Int -> StakeCredential -> ShowS
[StakeCredential] -> ShowS
StakeCredential -> String
(Int -> StakeCredential -> ShowS)
-> (StakeCredential -> String)
-> ([StakeCredential] -> ShowS)
-> Show StakeCredential
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [StakeCredential] -> ShowS
$cshowList :: [StakeCredential] -> ShowS
show :: StakeCredential -> String
$cshow :: StakeCredential -> String
showsPrec :: Int -> StakeCredential -> ShowS
$cshowsPrec :: Int -> StakeCredential -> ShowS
Show)

data StakeAddressReference
       = StakeAddressByValue   StakeCredential
       | StakeAddressByPointer StakeAddressPointer
       | NoStakeAddress
  deriving (StakeAddressReference -> StakeAddressReference -> Bool
(StakeAddressReference -> StakeAddressReference -> Bool)
-> (StakeAddressReference -> StakeAddressReference -> Bool)
-> Eq StakeAddressReference
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: StakeAddressReference -> StakeAddressReference -> Bool
$c/= :: StakeAddressReference -> StakeAddressReference -> Bool
== :: StakeAddressReference -> StakeAddressReference -> Bool
$c== :: StakeAddressReference -> StakeAddressReference -> Bool
Eq, Int -> StakeAddressReference -> ShowS
[StakeAddressReference] -> ShowS
StakeAddressReference -> String
(Int -> StakeAddressReference -> ShowS)
-> (StakeAddressReference -> String)
-> ([StakeAddressReference] -> ShowS)
-> Show StakeAddressReference
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [StakeAddressReference] -> ShowS
$cshowList :: [StakeAddressReference] -> ShowS
show :: StakeAddressReference -> String
$cshow :: StakeAddressReference -> String
showsPrec :: Int -> StakeAddressReference -> ShowS
$cshowsPrec :: Int -> StakeAddressReference -> ShowS
Show)

newtype StakeAddressPointer = StakeAddressPointer
  { StakeAddressPointer -> Ptr
unStakeAddressPointer :: Sophie.Ptr
  }
  deriving (StakeAddressPointer -> StakeAddressPointer -> Bool
(StakeAddressPointer -> StakeAddressPointer -> Bool)
-> (StakeAddressPointer -> StakeAddressPointer -> Bool)
-> Eq StakeAddressPointer
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: StakeAddressPointer -> StakeAddressPointer -> Bool
$c/= :: StakeAddressPointer -> StakeAddressPointer -> Bool
== :: StakeAddressPointer -> StakeAddressPointer -> Bool
$c== :: StakeAddressPointer -> StakeAddressPointer -> Bool
Eq, Int -> StakeAddressPointer -> ShowS
[StakeAddressPointer] -> ShowS
StakeAddressPointer -> String
(Int -> StakeAddressPointer -> ShowS)
-> (StakeAddressPointer -> String)
-> ([StakeAddressPointer] -> ShowS)
-> Show StakeAddressPointer
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [StakeAddressPointer] -> ShowS
$cshowList :: [StakeAddressPointer] -> ShowS
show :: StakeAddressPointer -> String
$cshow :: StakeAddressPointer -> String
showsPrec :: Int -> StakeAddressPointer -> ShowS
$cshowsPrec :: Int -> StakeAddressPointer -> ShowS
Show)

instance HasTypeProxy StakeAddress where
    data AsType StakeAddress = AsStakeAddress
    proxyToAsType :: Proxy StakeAddress -> AsType StakeAddress
proxyToAsType Proxy StakeAddress
_ = AsType StakeAddress
AsStakeAddress


instance SerialiseAsRawBytes StakeAddress where
    serialiseToRawBytes :: StakeAddress -> ByteString
serialiseToRawBytes (StakeAddress Network
nw StakeCredential StandardCrypto
sc) =
        RewardAcnt StandardCrypto -> ByteString
forall crypto. RewardAcnt crypto -> ByteString
Sophie.serialiseRewardAcnt (Network
-> StakeCredential StandardCrypto -> RewardAcnt StandardCrypto
forall crypto.
Network -> Credential 'Staking crypto -> RewardAcnt crypto
Sophie.RewardAcnt Network
nw StakeCredential StandardCrypto
sc)

    deserialiseFromRawBytes :: AsType StakeAddress -> ByteString -> Maybe StakeAddress
deserialiseFromRawBytes AsType StakeAddress
AsStakeAddress ByteString
bs =
        case ByteString -> Maybe (RewardAcnt StandardCrypto)
forall crypto.
Crypto crypto =>
ByteString -> Maybe (RewardAcnt crypto)
Sophie.deserialiseRewardAcnt ByteString
bs of
          Maybe (RewardAcnt StandardCrypto)
Nothing -> Maybe StakeAddress
forall a. Maybe a
Nothing
          Just (Sophie.RewardAcnt Network
nw StakeCredential StandardCrypto
sc) -> StakeAddress -> Maybe StakeAddress
forall a. a -> Maybe a
Just (Network -> StakeCredential StandardCrypto -> StakeAddress
StakeAddress Network
nw StakeCredential StandardCrypto
sc)


instance SerialiseAsBech32 StakeAddress where
    bech32PrefixFor :: StakeAddress -> Text
bech32PrefixFor (StakeAddress Network
Sophie.Mainnet StakeCredential StandardCrypto
_) = Text
"stake"
    bech32PrefixFor (StakeAddress Network
Sophie.Testnet StakeCredential StandardCrypto
_) = Text
"stake_test"

    bech32PrefixesPermitted :: AsType StakeAddress -> [Text]
bech32PrefixesPermitted AsType StakeAddress
AsStakeAddress = [Text
"stake", Text
"stake_test"]


instance SerialiseAddress StakeAddress where
    serialiseAddress :: StakeAddress -> Text
serialiseAddress addr :: StakeAddress
addr@StakeAddress{} =
      StakeAddress -> Text
forall a. SerialiseAsBech32 a => a -> Text
serialiseToBech32 StakeAddress
addr

    deserialiseAddress :: AsType StakeAddress -> Text -> Maybe StakeAddress
deserialiseAddress AsType StakeAddress
AsStakeAddress Text
t =
      (Bech32DecodeError -> Maybe StakeAddress)
-> (StakeAddress -> Maybe StakeAddress)
-> Either Bech32DecodeError StakeAddress
-> Maybe StakeAddress
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Maybe StakeAddress -> Bech32DecodeError -> Maybe StakeAddress
forall a b. a -> b -> a
const Maybe StakeAddress
forall a. Maybe a
Nothing) StakeAddress -> Maybe StakeAddress
forall a. a -> Maybe a
Just (Either Bech32DecodeError StakeAddress -> Maybe StakeAddress)
-> Either Bech32DecodeError StakeAddress -> Maybe StakeAddress
forall a b. (a -> b) -> a -> b
$
      AsType StakeAddress
-> Text -> Either Bech32DecodeError StakeAddress
forall a.
SerialiseAsBech32 a =>
AsType a -> Text -> Either Bech32DecodeError a
deserialiseFromBech32 AsType StakeAddress
AsStakeAddress Text
t


makeStakeAddress :: NetworkId
                 -> StakeCredential
                 -> StakeAddress
makeStakeAddress :: NetworkId -> StakeCredential -> StakeAddress
makeStakeAddress NetworkId
nw StakeCredential
sc =
    Network -> StakeCredential StandardCrypto -> StakeAddress
StakeAddress
      (NetworkId -> Network
toSophieNetwork NetworkId
nw)
      (StakeCredential -> StakeCredential StandardCrypto
toSophieStakeCredential StakeCredential
sc)

-- ----------------------------------------------------------------------------
-- Helpers
--

-- | Is the UTxO at the address only spendable via a key witness.
isKeyAddress :: AddressInEra era -> Bool
isKeyAddress :: AddressInEra era -> Bool
isKeyAddress (AddressInEra AddressTypeInEra addrtype era
ColeAddressInAnyEra Address addrtype
_) = Bool
True
isKeyAddress (AddressInEra (SophieAddressInEra SophieBasedEra era
_) (SophieAddress Network
_ PaymentCredential StandardCrypto
pCred StakeReference StandardCrypto
_)) =
  case PaymentCredential StandardCrypto -> PaymentCredential
fromSophiePaymentCredential PaymentCredential StandardCrypto
pCred of
    PaymentCredentialByKey Hash PaymentKey
_ -> Bool
True
    PaymentCredentialByScript ScriptHash
_ -> Bool
False


-- ----------------------------------------------------------------------------
-- Internal conversion functions
--

toSophieAddr :: AddressInEra era -> Sophie.Addr StandardCrypto
toSophieAddr :: AddressInEra era -> Addr StandardCrypto
toSophieAddr (AddressInEra AddressTypeInEra addrtype era
ColeAddressInAnyEra (ColeAddress Address
addr)) =
    BootstrapAddress StandardCrypto -> Addr StandardCrypto
forall crypto. BootstrapAddress crypto -> Addr crypto
Sophie.AddrBootstrap (Address -> BootstrapAddress StandardCrypto
forall crypto. Address -> BootstrapAddress crypto
Sophie.BootstrapAddress Address
addr)
toSophieAddr (AddressInEra (SophieAddressInEra SophieBasedEra era
_)
                            (SophieAddress Network
nw PaymentCredential StandardCrypto
pc StakeReference StandardCrypto
scr)) =
    Network
-> PaymentCredential StandardCrypto
-> StakeReference StandardCrypto
-> Addr StandardCrypto
forall crypto.
Network
-> PaymentCredential crypto -> StakeReference crypto -> Addr crypto
Sophie.Addr Network
nw PaymentCredential StandardCrypto
pc StakeReference StandardCrypto
scr

toSophieStakeAddr :: StakeAddress -> Sophie.RewardAcnt StandardCrypto
toSophieStakeAddr :: StakeAddress -> RewardAcnt StandardCrypto
toSophieStakeAddr (StakeAddress Network
nw StakeCredential StandardCrypto
sc) =
    RewardAcnt :: forall crypto.
Network -> Credential 'Staking crypto -> RewardAcnt crypto
Sophie.RewardAcnt {
      getRwdNetwork :: Network
Sophie.getRwdNetwork = Network
nw,
      getRwdCred :: StakeCredential StandardCrypto
Sophie.getRwdCred    = StakeCredential StandardCrypto
sc
    }

toSophiePaymentCredential :: PaymentCredential
                           -> Sophie.PaymentCredential StandardCrypto
toSophiePaymentCredential :: PaymentCredential -> PaymentCredential StandardCrypto
toSophiePaymentCredential (PaymentCredentialByKey (PaymentKeyHash kh)) =
    KeyHash 'Payment StandardCrypto -> PaymentCredential StandardCrypto
forall (kr :: KeyRole) crypto.
KeyHash kr crypto -> Credential kr crypto
Sophie.KeyHashObj KeyHash 'Payment StandardCrypto
kh
toSophiePaymentCredential (PaymentCredentialByScript ScriptHash
sh) =
    ScriptHash StandardCrypto -> PaymentCredential StandardCrypto
forall (kr :: KeyRole) crypto.
ScriptHash crypto -> Credential kr crypto
Sophie.ScriptHashObj (ScriptHash -> ScriptHash StandardCrypto
toSophieScriptHash ScriptHash
sh)

toSophieStakeCredential :: StakeCredential
                         -> Sophie.StakeCredential StandardCrypto
toSophieStakeCredential :: StakeCredential -> StakeCredential StandardCrypto
toSophieStakeCredential (StakeCredentialByKey (StakeKeyHash kh)) =
    KeyHash 'Staking StandardCrypto -> StakeCredential StandardCrypto
forall (kr :: KeyRole) crypto.
KeyHash kr crypto -> Credential kr crypto
Sophie.KeyHashObj KeyHash 'Staking StandardCrypto
kh
toSophieStakeCredential (StakeCredentialByScript ScriptHash
sh) =
    ScriptHash StandardCrypto -> StakeCredential StandardCrypto
forall (kr :: KeyRole) crypto.
ScriptHash crypto -> Credential kr crypto
Sophie.ScriptHashObj (ScriptHash -> ScriptHash StandardCrypto
toSophieScriptHash ScriptHash
sh)

toSophieStakeReference :: StakeAddressReference
                        -> Sophie.StakeReference StandardCrypto
toSophieStakeReference :: StakeAddressReference -> StakeReference StandardCrypto
toSophieStakeReference (StakeAddressByValue StakeCredential
stakecred) =
    StakeCredential StandardCrypto -> StakeReference StandardCrypto
forall crypto. StakeCredential crypto -> StakeReference crypto
Sophie.StakeRefBase (StakeCredential -> StakeCredential StandardCrypto
toSophieStakeCredential StakeCredential
stakecred)
toSophieStakeReference (StakeAddressByPointer StakeAddressPointer
ptr) =
    Ptr -> StakeReference StandardCrypto
forall crypto. Ptr -> StakeReference crypto
Sophie.StakeRefPtr (StakeAddressPointer -> Ptr
unStakeAddressPointer StakeAddressPointer
ptr)
toSophieStakeReference  StakeAddressReference
NoStakeAddress =
    StakeReference StandardCrypto
forall crypto. StakeReference crypto
Sophie.StakeRefNull


fromSophieAddr :: IsSophieBasedEra era
                => Sophie.Addr StandardCrypto -> AddressInEra era
fromSophieAddr :: Addr StandardCrypto -> AddressInEra era
fromSophieAddr (Sophie.AddrBootstrap (Sophie.BootstrapAddress Address
addr)) =
    AddressTypeInEra ColeAddr era
-> Address ColeAddr -> AddressInEra era
forall addrtype era.
AddressTypeInEra addrtype era
-> Address addrtype -> AddressInEra era
AddressInEra AddressTypeInEra ColeAddr era
forall era. AddressTypeInEra ColeAddr era
ColeAddressInAnyEra (Address -> Address ColeAddr
ColeAddress Address
addr)

fromSophieAddr (Sophie.Addr Network
nw PaymentCredential StandardCrypto
pc StakeReference StandardCrypto
scr) =
    AddressTypeInEra SophieAddr era
-> Address SophieAddr -> AddressInEra era
forall addrtype era.
AddressTypeInEra addrtype era
-> Address addrtype -> AddressInEra era
AddressInEra
      (SophieBasedEra era -> AddressTypeInEra SophieAddr era
forall era. SophieBasedEra era -> AddressTypeInEra SophieAddr era
SophieAddressInEra SophieBasedEra era
forall era. IsSophieBasedEra era => SophieBasedEra era
sophieBasedEra)
      (Network
-> PaymentCredential StandardCrypto
-> StakeReference StandardCrypto
-> Address SophieAddr
SophieAddress Network
nw PaymentCredential StandardCrypto
pc StakeReference StandardCrypto
scr)

fromSophieStakeAddr :: Sophie.RewardAcnt StandardCrypto -> StakeAddress
fromSophieStakeAddr :: RewardAcnt StandardCrypto -> StakeAddress
fromSophieStakeAddr (Sophie.RewardAcnt Network
nw StakeCredential StandardCrypto
sc) = Network -> StakeCredential StandardCrypto -> StakeAddress
StakeAddress Network
nw StakeCredential StandardCrypto
sc

fromSophieStakeCredential :: Sophie.StakeCredential StandardCrypto
                           -> StakeCredential
fromSophieStakeCredential :: StakeCredential StandardCrypto -> StakeCredential
fromSophieStakeCredential (Sophie.KeyHashObj KeyHash 'Staking StandardCrypto
kh) =
    Hash StakeKey -> StakeCredential
StakeCredentialByKey (KeyHash 'Staking StandardCrypto -> Hash StakeKey
StakeKeyHash KeyHash 'Staking StandardCrypto
kh)
fromSophieStakeCredential (Sophie.ScriptHashObj ScriptHash StandardCrypto
sh) =
    ScriptHash -> StakeCredential
StakeCredentialByScript (ScriptHash StandardCrypto -> ScriptHash
fromSophieScriptHash ScriptHash StandardCrypto
sh)

fromSophiePaymentCredential :: Sophie.PaymentCredential StandardCrypto
                             -> PaymentCredential
fromSophiePaymentCredential :: PaymentCredential StandardCrypto -> PaymentCredential
fromSophiePaymentCredential (Sophie.KeyHashObj KeyHash 'Payment StandardCrypto
kh) =
  Hash PaymentKey -> PaymentCredential
PaymentCredentialByKey (KeyHash 'Payment StandardCrypto -> Hash PaymentKey
PaymentKeyHash KeyHash 'Payment StandardCrypto
kh)
fromSophiePaymentCredential (Sophie.ScriptHashObj ScriptHash StandardCrypto
sh) =
  ScriptHash -> PaymentCredential
PaymentCredentialByScript (ScriptHash StandardCrypto -> ScriptHash
ScriptHash ScriptHash StandardCrypto
sh)

fromSophieStakeReference :: Sophie.StakeReference StandardCrypto
                          -> StakeAddressReference
fromSophieStakeReference :: StakeReference StandardCrypto -> StakeAddressReference
fromSophieStakeReference (Sophie.StakeRefBase StakeCredential StandardCrypto
stakecred) =
  StakeCredential -> StakeAddressReference
StakeAddressByValue (StakeCredential StandardCrypto -> StakeCredential
fromSophieStakeCredential StakeCredential StandardCrypto
stakecred)
fromSophieStakeReference (Sophie.StakeRefPtr Ptr
ptr) =
  StakeAddressPointer -> StakeAddressReference
StakeAddressByPointer (Ptr -> StakeAddressPointer
StakeAddressPointer Ptr
ptr)
fromSophieStakeReference StakeReference StandardCrypto
Sophie.StakeRefNull =
  StakeAddressReference
NoStakeAddress