module Cardano.Ledger.Api.Tx.Address (
  -- * Address
  Addr (..),
  getNetwork,
  BootstrapAddress (..),
  serialiseAddr,

  -- ** Strict decoders

  -- | Decoders below will only decode addresses that are allowed to be placed on chain
  -- today. Historically there were a few bugs in the decoder which allowed a few
  -- malformed addressed to be placed on chain. If you need backwards compatibility, reach
  -- out for `decodeAddrLenient`.
  decodeAddr,
  decodeAddrEither,
  decodeAddrShort,
  decodeAddrShortEither,

  -- ** Lenient decoders

  -- | These lenient decoders do not fail for addresses with known bugs
  DecAddr (..),
  decodeAddrLenient,
  decodeAddrLenientEither,

  -- * Reward Account
  RewardAccount (..),
  serialiseRewardAccount,
  deserialiseRewardAccount,
)
where

import Cardano.Ledger.Address
import Control.Applicative ((<|>))
import Control.Monad.Trans.Fail (runFail, runFailLast)
import Control.Monad.Trans.State.Strict (evalStateT, get)
import qualified Data.ByteString as BS
import Data.ByteString.Short (ShortByteString)

-- | Same as `decodeAddrShort`, but produces an `Either` result
decodeAddrShortEither ::
  ShortByteString ->
  Either String Addr
decodeAddrShortEither :: ShortByteString -> Either String Addr
decodeAddrShortEither ShortByteString
sbs = forall e a. (IsString e, Semigroup e) => Fail e a -> Either e a
runFail forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
evalStateT (forall (m :: * -> *) b.
(MonadFail m, AddressBuffer b) =>
b -> StateT Int m Addr
decodeAddrStateT ShortByteString
sbs) Int
0
{-# INLINE decodeAddrShortEither #-}

-- | Same as `decodeAddr`, but works on `ShortByteString`
decodeAddrShort ::
  MonadFail m =>
  ShortByteString ->
  m Addr
decodeAddrShort :: forall (m :: * -> *). MonadFail m => ShortByteString -> m Addr
decodeAddrShort ShortByteString
sbs = forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
evalStateT (forall (m :: * -> *) b.
(MonadFail m, AddressBuffer b) =>
b -> StateT Int m Addr
decodeAddrStateT ShortByteString
sbs) Int
0
{-# INLINE decodeAddrShort #-}

-- | Decoded Address.
data DecAddr
  = -- | Address was decoded with no problems
    DecAddr Addr
  | -- | Address was decoded, but it contains an invalid `Cardano.Ledger.Credential.Ptr`
    DecAddrBadPtr Addr
  | -- | Address was decoded, but not all of input was consumed
    DecAddrUnconsumed
      Addr
      -- | Left over bytes after consuming the input
      BS.ByteString
  deriving (DecAddr -> DecAddr -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DecAddr -> DecAddr -> Bool
$c/= :: DecAddr -> DecAddr -> Bool
== :: DecAddr -> DecAddr -> Bool
$c== :: DecAddr -> DecAddr -> Bool
Eq, Int -> DecAddr -> ShowS
[DecAddr] -> ShowS
DecAddr -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DecAddr] -> ShowS
$cshowList :: [DecAddr] -> ShowS
show :: DecAddr -> String
$cshow :: DecAddr -> String
showsPrec :: Int -> DecAddr -> ShowS
$cshowsPrec :: Int -> DecAddr -> ShowS
Show)

-- | This is a lenient decoder that will disregard known bugs in the address
-- deserialization. This function is intended for clients that need to deal with
-- historical data that has already been placed on chain. If you also require information
-- on what exactly is bad in the address, or you would like to guard only against a
-- specific bug, you should use `decodeAddrLenientEither` instead.
--
-- @since 1.8.0
decodeAddrLenient ::
  MonadFail m =>
  BS.ByteString ->
  m Addr
decodeAddrLenient :: forall (m :: * -> *). MonadFail m => ByteString -> m Addr
decodeAddrLenient ByteString
bs = forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
evalStateT (forall (m :: * -> *) b.
(MonadFail m, AddressBuffer b) =>
Bool -> Bool -> b -> StateT Int m Addr
decodeAddrStateLenientT Bool
True Bool
True ByteString
bs) Int
0

-- | Decode an address and fail only for addresses that could have never been placed on
-- chain, while decoding addresses with information about potential problems in
-- them. Similar to `decodeAddrLenient`, this function is not intended for addresses that
-- will be placed into a new transaction.
--
-- @since 1.8.0
decodeAddrLenientEither ::
  BS.ByteString ->
  Either String DecAddr
decodeAddrLenientEither :: ByteString -> Either String DecAddr
decodeAddrLenientEither ByteString
bs =
  forall e a. IsString e => Fail e a -> Either e a
runFailLast forall a b. (a -> b) -> a -> b
$
    (Addr -> DecAddr
DecAddr forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *). MonadFail m => ByteString -> m Addr
decodeAddr ByteString
bs)
      forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Addr -> DecAddr
DecAddrBadPtr forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
evalStateT (forall (m :: * -> *) b.
(MonadFail m, AddressBuffer b) =>
Bool -> Bool -> b -> StateT Int m Addr
decodeAddrStateLenientT Bool
True Bool
False ByteString
bs) Int
0)
      forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> FailT String Identity DecAddr
decodeWithUnconsumed
  where
    decodeWithUnconsumed :: FailT String Identity DecAddr
decodeWithUnconsumed = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
evalStateT Int
0 forall a b. (a -> b) -> a -> b
$ do
      Addr
addr <- forall (m :: * -> *) b.
(MonadFail m, AddressBuffer b) =>
Bool -> Bool -> b -> StateT Int m Addr
decodeAddrStateLenientT Bool
False Bool
True ByteString
bs
      Int
bytesConsumed <- forall (m :: * -> *) s. Monad m => StateT s m s
get
      forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ Addr -> ByteString -> DecAddr
DecAddrUnconsumed Addr
addr (Int -> ByteString -> ByteString
BS.drop Int
bytesConsumed ByteString
bs)