{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ViewPatterns #-}

module Cardano.Wallet.Primitive.Types.TokenPolicy
    (
      -- * Token Policies
      TokenPolicyId (..)

      -- * Token Names
    , TokenName (..)
    , mkTokenName
    , nullTokenName
    , tokenNameMaxLength

      -- * Token Fingerprints
    , TokenFingerprint (..)
    , mkTokenFingerprint

      -- * Token Metadata
    , AssetMetadata (..)
    , AssetURL (..)
    , AssetLogo (..)
    , AssetDecimals (..)
    , validateMetadataDecimals
    , validateMetadataName
    , validateMetadataTicker
    , validateMetadataDescription
    , validateMetadataURL
    , validateMetadataLogo
    ) where

import Prelude

import Cardano.Wallet.Primitive.Types.Hash
    ( Hash (..) )
import Codec.Binary.Bech32.TH
    ( humanReadablePart )
import Control.DeepSeq
    ( NFData )
import Control.Monad
    ( (>=>) )
import Crypto.Hash
    ( hash )
import Crypto.Hash.Algorithms
    ( Blake2b_160 )
import Data.Aeson
    ( FromJSON (..), ToJSON (..) )
import Data.Bifunctor
    ( first )
import Data.ByteArray
    ( convert )
import Data.ByteArray.Encoding
    ( Base (Base16), convertFromBase, convertToBase )
import Data.ByteString
    ( ByteString )
import Data.Function
    ( (&) )
import Data.Hashable
    ( Hashable )
import Data.Text
    ( Text )
import Data.Text.Class
    ( FromText (..), TextDecodingError (..), ToText (..) )
import Fmt
    ( Buildable (..) )
import GHC.Generics
    ( Generic )
import Network.URI
    ( URI, parseAbsoluteURI, uriScheme )
import Quiet
    ( Quiet (..) )

import qualified Codec.Binary.Bech32 as Bech32
import qualified Data.ByteString as BS
import qualified Data.Text as T
import qualified Data.Text.Encoding as T

-- | Token policy identifiers, represented by the hash of the monetary policy
-- script.
newtype TokenPolicyId =
    -- | Construct a 'TokenPolicyId' without any validation.
    UnsafeTokenPolicyId { TokenPolicyId -> Hash "TokenPolicy"
unTokenPolicyId :: Hash "TokenPolicy" }
    deriving stock (TokenPolicyId -> TokenPolicyId -> Bool
(TokenPolicyId -> TokenPolicyId -> Bool)
-> (TokenPolicyId -> TokenPolicyId -> Bool) -> Eq TokenPolicyId
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TokenPolicyId -> TokenPolicyId -> Bool
$c/= :: TokenPolicyId -> TokenPolicyId -> Bool
== :: TokenPolicyId -> TokenPolicyId -> Bool
$c== :: TokenPolicyId -> TokenPolicyId -> Bool
Eq, Eq TokenPolicyId
Eq TokenPolicyId
-> (TokenPolicyId -> TokenPolicyId -> Ordering)
-> (TokenPolicyId -> TokenPolicyId -> Bool)
-> (TokenPolicyId -> TokenPolicyId -> Bool)
-> (TokenPolicyId -> TokenPolicyId -> Bool)
-> (TokenPolicyId -> TokenPolicyId -> Bool)
-> (TokenPolicyId -> TokenPolicyId -> TokenPolicyId)
-> (TokenPolicyId -> TokenPolicyId -> TokenPolicyId)
-> Ord TokenPolicyId
TokenPolicyId -> TokenPolicyId -> Bool
TokenPolicyId -> TokenPolicyId -> Ordering
TokenPolicyId -> TokenPolicyId -> TokenPolicyId
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 :: TokenPolicyId -> TokenPolicyId -> TokenPolicyId
$cmin :: TokenPolicyId -> TokenPolicyId -> TokenPolicyId
max :: TokenPolicyId -> TokenPolicyId -> TokenPolicyId
$cmax :: TokenPolicyId -> TokenPolicyId -> TokenPolicyId
>= :: TokenPolicyId -> TokenPolicyId -> Bool
$c>= :: TokenPolicyId -> TokenPolicyId -> Bool
> :: TokenPolicyId -> TokenPolicyId -> Bool
$c> :: TokenPolicyId -> TokenPolicyId -> Bool
<= :: TokenPolicyId -> TokenPolicyId -> Bool
$c<= :: TokenPolicyId -> TokenPolicyId -> Bool
< :: TokenPolicyId -> TokenPolicyId -> Bool
$c< :: TokenPolicyId -> TokenPolicyId -> Bool
compare :: TokenPolicyId -> TokenPolicyId -> Ordering
$ccompare :: TokenPolicyId -> TokenPolicyId -> Ordering
$cp1Ord :: Eq TokenPolicyId
Ord, (forall x. TokenPolicyId -> Rep TokenPolicyId x)
-> (forall x. Rep TokenPolicyId x -> TokenPolicyId)
-> Generic TokenPolicyId
forall x. Rep TokenPolicyId x -> TokenPolicyId
forall x. TokenPolicyId -> Rep TokenPolicyId x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep TokenPolicyId x -> TokenPolicyId
$cfrom :: forall x. TokenPolicyId -> Rep TokenPolicyId x
Generic)
    deriving (ReadPrec [TokenPolicyId]
ReadPrec TokenPolicyId
Int -> ReadS TokenPolicyId
ReadS [TokenPolicyId]
(Int -> ReadS TokenPolicyId)
-> ReadS [TokenPolicyId]
-> ReadPrec TokenPolicyId
-> ReadPrec [TokenPolicyId]
-> Read TokenPolicyId
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [TokenPolicyId]
$creadListPrec :: ReadPrec [TokenPolicyId]
readPrec :: ReadPrec TokenPolicyId
$creadPrec :: ReadPrec TokenPolicyId
readList :: ReadS [TokenPolicyId]
$creadList :: ReadS [TokenPolicyId]
readsPrec :: Int -> ReadS TokenPolicyId
$creadsPrec :: Int -> ReadS TokenPolicyId
Read, Int -> TokenPolicyId -> ShowS
[TokenPolicyId] -> ShowS
TokenPolicyId -> String
(Int -> TokenPolicyId -> ShowS)
-> (TokenPolicyId -> String)
-> ([TokenPolicyId] -> ShowS)
-> Show TokenPolicyId
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TokenPolicyId] -> ShowS
$cshowList :: [TokenPolicyId] -> ShowS
show :: TokenPolicyId -> String
$cshow :: TokenPolicyId -> String
showsPrec :: Int -> TokenPolicyId -> ShowS
$cshowsPrec :: Int -> TokenPolicyId -> ShowS
Show) via (Quiet TokenPolicyId)
    deriving anyclass Int -> TokenPolicyId -> Int
TokenPolicyId -> Int
(Int -> TokenPolicyId -> Int)
-> (TokenPolicyId -> Int) -> Hashable TokenPolicyId
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: TokenPolicyId -> Int
$chash :: TokenPolicyId -> Int
hashWithSalt :: Int -> TokenPolicyId -> Int
$chashWithSalt :: Int -> TokenPolicyId -> Int
Hashable

instance NFData TokenPolicyId

instance Buildable TokenPolicyId where
    build :: TokenPolicyId -> Builder
build = Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder)
-> (TokenPolicyId -> Text) -> TokenPolicyId -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Hash "TokenPolicy" -> Text
forall a. ToText a => a -> Text
toText (Hash "TokenPolicy" -> Text)
-> (TokenPolicyId -> Hash "TokenPolicy") -> TokenPolicyId -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TokenPolicyId -> Hash "TokenPolicy"
unTokenPolicyId

instance FromJSON TokenPolicyId where
    parseJSON :: Value -> Parser TokenPolicyId
parseJSON = Value -> Parser Text
forall a. FromJSON a => Value -> Parser a
parseJSON (Value -> Parser Text)
-> (Text -> Parser TokenPolicyId) -> Value -> Parser TokenPolicyId
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> (TextDecodingError -> Parser TokenPolicyId)
-> (TokenPolicyId -> Parser TokenPolicyId)
-> Either TextDecodingError TokenPolicyId
-> Parser TokenPolicyId
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (String -> Parser TokenPolicyId
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Parser TokenPolicyId)
-> (TextDecodingError -> String)
-> TextDecodingError
-> Parser TokenPolicyId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TextDecodingError -> String
forall a. Show a => a -> String
show) TokenPolicyId -> Parser TokenPolicyId
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either TextDecodingError TokenPolicyId -> Parser TokenPolicyId)
-> (Text -> Either TextDecodingError TokenPolicyId)
-> Text
-> Parser TokenPolicyId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Either TextDecodingError TokenPolicyId
forall a. FromText a => Text -> Either TextDecodingError a
fromText

instance ToJSON TokenPolicyId where
    toJSON :: TokenPolicyId -> Value
toJSON = Text -> Value
forall a. ToJSON a => a -> Value
toJSON (Text -> Value)
-> (TokenPolicyId -> Text) -> TokenPolicyId -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TokenPolicyId -> Text
forall a. ToText a => a -> Text
toText

instance ToText TokenPolicyId where
    toText :: TokenPolicyId -> Text
toText = Hash "TokenPolicy" -> Text
forall a. ToText a => a -> Text
toText (Hash "TokenPolicy" -> Text)
-> (TokenPolicyId -> Hash "TokenPolicy") -> TokenPolicyId -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TokenPolicyId -> Hash "TokenPolicy"
unTokenPolicyId

instance FromText TokenPolicyId where
    fromText :: Text -> Either TextDecodingError TokenPolicyId
fromText = (Hash "TokenPolicy" -> TokenPolicyId)
-> Either TextDecodingError (Hash "TokenPolicy")
-> Either TextDecodingError TokenPolicyId
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Hash "TokenPolicy" -> TokenPolicyId
UnsafeTokenPolicyId (Either TextDecodingError (Hash "TokenPolicy")
 -> Either TextDecodingError TokenPolicyId)
-> (Text -> Either TextDecodingError (Hash "TokenPolicy"))
-> Text
-> Either TextDecodingError TokenPolicyId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Either TextDecodingError (Hash "TokenPolicy")
forall a. FromText a => Text -> Either TextDecodingError a
fromText

-- | Token names, defined by the monetary policy script.
newtype TokenName =
    -- | Construct a 'TokenName' without any validation.
    UnsafeTokenName { TokenName -> ByteString
unTokenName :: ByteString }
    deriving stock (TokenName -> TokenName -> Bool
(TokenName -> TokenName -> Bool)
-> (TokenName -> TokenName -> Bool) -> Eq TokenName
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TokenName -> TokenName -> Bool
$c/= :: TokenName -> TokenName -> Bool
== :: TokenName -> TokenName -> Bool
$c== :: TokenName -> TokenName -> Bool
Eq, Eq TokenName
Eq TokenName
-> (TokenName -> TokenName -> Ordering)
-> (TokenName -> TokenName -> Bool)
-> (TokenName -> TokenName -> Bool)
-> (TokenName -> TokenName -> Bool)
-> (TokenName -> TokenName -> Bool)
-> (TokenName -> TokenName -> TokenName)
-> (TokenName -> TokenName -> TokenName)
-> Ord TokenName
TokenName -> TokenName -> Bool
TokenName -> TokenName -> Ordering
TokenName -> TokenName -> TokenName
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 :: TokenName -> TokenName -> TokenName
$cmin :: TokenName -> TokenName -> TokenName
max :: TokenName -> TokenName -> TokenName
$cmax :: TokenName -> TokenName -> TokenName
>= :: TokenName -> TokenName -> Bool
$c>= :: TokenName -> TokenName -> Bool
> :: TokenName -> TokenName -> Bool
$c> :: TokenName -> TokenName -> Bool
<= :: TokenName -> TokenName -> Bool
$c<= :: TokenName -> TokenName -> Bool
< :: TokenName -> TokenName -> Bool
$c< :: TokenName -> TokenName -> Bool
compare :: TokenName -> TokenName -> Ordering
$ccompare :: TokenName -> TokenName -> Ordering
$cp1Ord :: Eq TokenName
Ord, (forall x. TokenName -> Rep TokenName x)
-> (forall x. Rep TokenName x -> TokenName) -> Generic TokenName
forall x. Rep TokenName x -> TokenName
forall x. TokenName -> Rep TokenName x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep TokenName x -> TokenName
$cfrom :: forall x. TokenName -> Rep TokenName x
Generic)
    deriving (ReadPrec [TokenName]
ReadPrec TokenName
Int -> ReadS TokenName
ReadS [TokenName]
(Int -> ReadS TokenName)
-> ReadS [TokenName]
-> ReadPrec TokenName
-> ReadPrec [TokenName]
-> Read TokenName
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [TokenName]
$creadListPrec :: ReadPrec [TokenName]
readPrec :: ReadPrec TokenName
$creadPrec :: ReadPrec TokenName
readList :: ReadS [TokenName]
$creadList :: ReadS [TokenName]
readsPrec :: Int -> ReadS TokenName
$creadsPrec :: Int -> ReadS TokenName
Read, Int -> TokenName -> ShowS
[TokenName] -> ShowS
TokenName -> String
(Int -> TokenName -> ShowS)
-> (TokenName -> String)
-> ([TokenName] -> ShowS)
-> Show TokenName
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TokenName] -> ShowS
$cshowList :: [TokenName] -> ShowS
show :: TokenName -> String
$cshow :: TokenName -> String
showsPrec :: Int -> TokenName -> ShowS
$cshowsPrec :: Int -> TokenName -> ShowS
Show) via (Quiet TokenName)
    deriving anyclass Int -> TokenName -> Int
TokenName -> Int
(Int -> TokenName -> Int)
-> (TokenName -> Int) -> Hashable TokenName
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: TokenName -> Int
$chash :: TokenName -> Int
hashWithSalt :: Int -> TokenName -> Int
$chashWithSalt :: Int -> TokenName -> Int
Hashable

-- | Construct a 'TokenName', validating that the length does not exceed
--   'tokenNameMaxLength'.
--
mkTokenName :: ByteString -> Either String TokenName
mkTokenName :: ByteString -> Either String TokenName
mkTokenName ByteString
bs
    | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
tokenNameMaxLength = TokenName -> Either String TokenName
forall a b. b -> Either a b
Right (TokenName -> Either String TokenName)
-> TokenName -> Either String TokenName
forall a b. (a -> b) -> a -> b
$ ByteString -> TokenName
UnsafeTokenName ByteString
bs
    | Bool
otherwise = String -> Either String TokenName
forall a b. a -> Either a b
Left (String -> Either String TokenName)
-> String -> Either String TokenName
forall a b. (a -> b) -> a -> b
$ String
"TokenName length " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show (ByteString -> Int
BS.length ByteString
bs)
        String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" exceeds maximum of " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
tokenNameMaxLength

-- | The empty asset name.
--
-- Asset names may be empty, where a monetary policy script only mints a single
-- asset, or where one asset should be considered as the "default" token for the
-- policy.
--
nullTokenName :: TokenName
nullTokenName :: TokenName
nullTokenName = ByteString -> TokenName
UnsafeTokenName ByteString
""

-- | The maximum length of a valid token name.
--
tokenNameMaxLength :: Int
tokenNameMaxLength :: Int
tokenNameMaxLength = Int
32

instance NFData TokenName

instance Buildable TokenName where
    build :: TokenName -> Builder
build = Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> (TokenName -> Text) -> TokenName -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TokenName -> Text
forall a. ToText a => a -> Text
toText

instance FromJSON TokenName where
    parseJSON :: Value -> Parser TokenName
parseJSON = Value -> Parser Text
forall a. FromJSON a => Value -> Parser a
parseJSON (Value -> Parser Text)
-> (Text -> Parser TokenName) -> Value -> Parser TokenName
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> (TextDecodingError -> Parser TokenName)
-> (TokenName -> Parser TokenName)
-> Either TextDecodingError TokenName
-> Parser TokenName
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (String -> Parser TokenName
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Parser TokenName)
-> (TextDecodingError -> String)
-> TextDecodingError
-> Parser TokenName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TextDecodingError -> String
forall a. Show a => a -> String
show) TokenName -> Parser TokenName
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either TextDecodingError TokenName -> Parser TokenName)
-> (Text -> Either TextDecodingError TokenName)
-> Text
-> Parser TokenName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Either TextDecodingError TokenName
forall a. FromText a => Text -> Either TextDecodingError a
fromText

instance ToJSON TokenName where
    toJSON :: TokenName -> Value
toJSON = Text -> Value
forall a. ToJSON a => a -> Value
toJSON (Text -> Value) -> (TokenName -> Text) -> TokenName -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TokenName -> Text
forall a. ToText a => a -> Text
toText

instance ToText TokenName where
    toText :: TokenName -> Text
toText = ByteString -> Text
T.decodeLatin1 (ByteString -> Text)
-> (TokenName -> ByteString) -> TokenName -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Base -> ByteString -> ByteString
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
Base -> bin -> bout
convertToBase Base
Base16 (ByteString -> ByteString)
-> (TokenName -> ByteString) -> TokenName -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TokenName -> ByteString
unTokenName

instance FromText TokenName where
    fromText :: Text -> Either TextDecodingError TokenName
fromText = (String -> TextDecodingError)
-> Either String TokenName -> Either TextDecodingError TokenName
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first String -> TextDecodingError
TextDecodingError
        (Either String TokenName -> Either TextDecodingError TokenName)
-> (Text -> Either String TokenName)
-> Text
-> Either TextDecodingError TokenName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Either String TokenName)
-> (ByteString -> Either String TokenName)
-> Either String ByteString
-> Either String TokenName
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (String -> Either String TokenName
forall a b. a -> Either a b
Left (String -> Either String TokenName)
-> ShowS -> String -> Either String TokenName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"TokenName is not hex-encoded: " String -> ShowS
forall a. [a] -> [a] -> [a]
++)) ByteString -> Either String TokenName
mkTokenName
        (Either String ByteString -> Either String TokenName)
-> (Text -> Either String ByteString)
-> Text
-> Either String TokenName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Base -> ByteString -> Either String ByteString
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
Base -> bin -> Either String bout
convertFromBase Base
Base16
        (ByteString -> Either String ByteString)
-> (Text -> ByteString) -> Text -> Either String ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
T.encodeUtf8

newtype TokenFingerprint =
    UnsafeTokenFingerprint { TokenFingerprint -> Text
unTokenFingerprint :: Text }
    deriving stock (TokenFingerprint -> TokenFingerprint -> Bool
(TokenFingerprint -> TokenFingerprint -> Bool)
-> (TokenFingerprint -> TokenFingerprint -> Bool)
-> Eq TokenFingerprint
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TokenFingerprint -> TokenFingerprint -> Bool
$c/= :: TokenFingerprint -> TokenFingerprint -> Bool
== :: TokenFingerprint -> TokenFingerprint -> Bool
$c== :: TokenFingerprint -> TokenFingerprint -> Bool
Eq, Eq TokenFingerprint
Eq TokenFingerprint
-> (TokenFingerprint -> TokenFingerprint -> Ordering)
-> (TokenFingerprint -> TokenFingerprint -> Bool)
-> (TokenFingerprint -> TokenFingerprint -> Bool)
-> (TokenFingerprint -> TokenFingerprint -> Bool)
-> (TokenFingerprint -> TokenFingerprint -> Bool)
-> (TokenFingerprint -> TokenFingerprint -> TokenFingerprint)
-> (TokenFingerprint -> TokenFingerprint -> TokenFingerprint)
-> Ord TokenFingerprint
TokenFingerprint -> TokenFingerprint -> Bool
TokenFingerprint -> TokenFingerprint -> Ordering
TokenFingerprint -> TokenFingerprint -> TokenFingerprint
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 :: TokenFingerprint -> TokenFingerprint -> TokenFingerprint
$cmin :: TokenFingerprint -> TokenFingerprint -> TokenFingerprint
max :: TokenFingerprint -> TokenFingerprint -> TokenFingerprint
$cmax :: TokenFingerprint -> TokenFingerprint -> TokenFingerprint
>= :: TokenFingerprint -> TokenFingerprint -> Bool
$c>= :: TokenFingerprint -> TokenFingerprint -> Bool
> :: TokenFingerprint -> TokenFingerprint -> Bool
$c> :: TokenFingerprint -> TokenFingerprint -> Bool
<= :: TokenFingerprint -> TokenFingerprint -> Bool
$c<= :: TokenFingerprint -> TokenFingerprint -> Bool
< :: TokenFingerprint -> TokenFingerprint -> Bool
$c< :: TokenFingerprint -> TokenFingerprint -> Bool
compare :: TokenFingerprint -> TokenFingerprint -> Ordering
$ccompare :: TokenFingerprint -> TokenFingerprint -> Ordering
$cp1Ord :: Eq TokenFingerprint
Ord, (forall x. TokenFingerprint -> Rep TokenFingerprint x)
-> (forall x. Rep TokenFingerprint x -> TokenFingerprint)
-> Generic TokenFingerprint
forall x. Rep TokenFingerprint x -> TokenFingerprint
forall x. TokenFingerprint -> Rep TokenFingerprint x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep TokenFingerprint x -> TokenFingerprint
$cfrom :: forall x. TokenFingerprint -> Rep TokenFingerprint x
Generic)
    deriving (ReadPrec [TokenFingerprint]
ReadPrec TokenFingerprint
Int -> ReadS TokenFingerprint
ReadS [TokenFingerprint]
(Int -> ReadS TokenFingerprint)
-> ReadS [TokenFingerprint]
-> ReadPrec TokenFingerprint
-> ReadPrec [TokenFingerprint]
-> Read TokenFingerprint
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [TokenFingerprint]
$creadListPrec :: ReadPrec [TokenFingerprint]
readPrec :: ReadPrec TokenFingerprint
$creadPrec :: ReadPrec TokenFingerprint
readList :: ReadS [TokenFingerprint]
$creadList :: ReadS [TokenFingerprint]
readsPrec :: Int -> ReadS TokenFingerprint
$creadsPrec :: Int -> ReadS TokenFingerprint
Read, Int -> TokenFingerprint -> ShowS
[TokenFingerprint] -> ShowS
TokenFingerprint -> String
(Int -> TokenFingerprint -> ShowS)
-> (TokenFingerprint -> String)
-> ([TokenFingerprint] -> ShowS)
-> Show TokenFingerprint
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TokenFingerprint] -> ShowS
$cshowList :: [TokenFingerprint] -> ShowS
show :: TokenFingerprint -> String
$cshow :: TokenFingerprint -> String
showsPrec :: Int -> TokenFingerprint -> ShowS
$cshowsPrec :: Int -> TokenFingerprint -> ShowS
Show) via (Quiet TokenFingerprint)
    deriving anyclass Int -> TokenFingerprint -> Int
TokenFingerprint -> Int
(Int -> TokenFingerprint -> Int)
-> (TokenFingerprint -> Int) -> Hashable TokenFingerprint
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: TokenFingerprint -> Int
$chash :: TokenFingerprint -> Int
hashWithSalt :: Int -> TokenFingerprint -> Int
$chashWithSalt :: Int -> TokenFingerprint -> Int
Hashable

instance NFData TokenFingerprint

-- | Construct a fingerprint from a 'TokenPolicyId' and 'TokenName'. The
-- fingerprint is not necessarily unique, but can be used in user-facing
-- interfaces as a comparison mechanism.
mkTokenFingerprint :: TokenPolicyId -> TokenName -> TokenFingerprint
mkTokenFingerprint :: TokenPolicyId -> TokenName -> TokenFingerprint
mkTokenFingerprint (UnsafeTokenPolicyId (Hash ByteString
p)) (UnsafeTokenName ByteString
n)
    = (ByteString
p ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
n)
    ByteString -> (ByteString -> ByteString) -> ByteString
forall a b. a -> (a -> b) -> b
& Digest Blake2b_160 -> ByteString
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
convert (Digest Blake2b_160 -> ByteString)
-> (ByteString -> Digest Blake2b_160) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteArrayAccess ByteString, HashAlgorithm Blake2b_160) =>
ByteString -> Digest Blake2b_160
forall ba a.
(ByteArrayAccess ba, HashAlgorithm a) =>
ba -> Digest a
hash @_ @Blake2b_160
    ByteString -> (ByteString -> Text) -> Text
forall a b. a -> (a -> b) -> b
& HumanReadablePart -> DataPart -> Text
Bech32.encodeLenient HumanReadablePart
tokenFingerprintHrp (DataPart -> Text)
-> (ByteString -> DataPart) -> ByteString -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> DataPart
Bech32.dataPartFromBytes
    Text -> (Text -> TokenFingerprint) -> TokenFingerprint
forall a b. a -> (a -> b) -> b
& Text -> TokenFingerprint
UnsafeTokenFingerprint

tokenFingerprintHrp :: Bech32.HumanReadablePart
tokenFingerprintHrp :: HumanReadablePart
tokenFingerprintHrp = [humanReadablePart|asset|]

instance ToText TokenFingerprint where
    toText :: TokenFingerprint -> Text
toText = TokenFingerprint -> Text
unTokenFingerprint

instance FromText TokenFingerprint where
    fromText :: Text -> Either TextDecodingError TokenFingerprint
fromText Text
txt = case Text -> Either DecodingError (HumanReadablePart, DataPart)
Bech32.decodeLenient Text
txt of
        Left{} -> TextDecodingError -> Either TextDecodingError TokenFingerprint
forall a b. a -> Either a b
Left TextDecodingError
invalidBech32String
        Right (HumanReadablePart
hrp, DataPart
dp)
            | HumanReadablePart
hrp HumanReadablePart -> HumanReadablePart -> Bool
forall a. Eq a => a -> a -> Bool
/= HumanReadablePart
tokenFingerprintHrp -> TextDecodingError -> Either TextDecodingError TokenFingerprint
forall a b. a -> Either a b
Left TextDecodingError
unrecognizedHrp
            | Bool
otherwise -> case ByteString -> Int
BS.length (ByteString -> Int) -> Maybe ByteString -> Maybe Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DataPart -> Maybe ByteString
Bech32.dataPartToBytes DataPart
dp of
                Just Int
20 -> TokenFingerprint -> Either TextDecodingError TokenFingerprint
forall a b. b -> Either a b
Right (Text -> TokenFingerprint
UnsafeTokenFingerprint Text
txt)
                Maybe Int
_ -> TextDecodingError -> Either TextDecodingError TokenFingerprint
forall a b. a -> Either a b
Left TextDecodingError
invalidDatapart
      where
        invalidBech32String :: TextDecodingError
invalidBech32String = String -> TextDecodingError
TextDecodingError
            String
"A 'TokenFingerprint' must be a valid bech32-encoded string."
        unrecognizedHrp :: TextDecodingError
unrecognizedHrp = String -> TextDecodingError
TextDecodingError
            String
"Expected 'asset' as a human-readable part, but got something else."
        invalidDatapart :: TextDecodingError
invalidDatapart = String -> TextDecodingError
TextDecodingError
            String
"Expected a Blake2b-160 digest as data payload, but got something else."

-- | Information about an asset, from a source external to the chain.
data AssetMetadata = AssetMetadata
    { AssetMetadata -> Text
name :: Text
    , AssetMetadata -> Text
description :: Text
    , AssetMetadata -> Maybe Text
ticker :: Maybe Text
    , AssetMetadata -> Maybe AssetURL
url :: Maybe AssetURL
    , AssetMetadata -> Maybe AssetLogo
logo :: Maybe AssetLogo
    , AssetMetadata -> Maybe AssetDecimals
decimals :: Maybe AssetDecimals
    } deriving stock (AssetMetadata -> AssetMetadata -> Bool
(AssetMetadata -> AssetMetadata -> Bool)
-> (AssetMetadata -> AssetMetadata -> Bool) -> Eq AssetMetadata
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AssetMetadata -> AssetMetadata -> Bool
$c/= :: AssetMetadata -> AssetMetadata -> Bool
== :: AssetMetadata -> AssetMetadata -> Bool
$c== :: AssetMetadata -> AssetMetadata -> Bool
Eq, Eq AssetMetadata
Eq AssetMetadata
-> (AssetMetadata -> AssetMetadata -> Ordering)
-> (AssetMetadata -> AssetMetadata -> Bool)
-> (AssetMetadata -> AssetMetadata -> Bool)
-> (AssetMetadata -> AssetMetadata -> Bool)
-> (AssetMetadata -> AssetMetadata -> Bool)
-> (AssetMetadata -> AssetMetadata -> AssetMetadata)
-> (AssetMetadata -> AssetMetadata -> AssetMetadata)
-> Ord AssetMetadata
AssetMetadata -> AssetMetadata -> Bool
AssetMetadata -> AssetMetadata -> Ordering
AssetMetadata -> AssetMetadata -> AssetMetadata
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 :: AssetMetadata -> AssetMetadata -> AssetMetadata
$cmin :: AssetMetadata -> AssetMetadata -> AssetMetadata
max :: AssetMetadata -> AssetMetadata -> AssetMetadata
$cmax :: AssetMetadata -> AssetMetadata -> AssetMetadata
>= :: AssetMetadata -> AssetMetadata -> Bool
$c>= :: AssetMetadata -> AssetMetadata -> Bool
> :: AssetMetadata -> AssetMetadata -> Bool
$c> :: AssetMetadata -> AssetMetadata -> Bool
<= :: AssetMetadata -> AssetMetadata -> Bool
$c<= :: AssetMetadata -> AssetMetadata -> Bool
< :: AssetMetadata -> AssetMetadata -> Bool
$c< :: AssetMetadata -> AssetMetadata -> Bool
compare :: AssetMetadata -> AssetMetadata -> Ordering
$ccompare :: AssetMetadata -> AssetMetadata -> Ordering
$cp1Ord :: Eq AssetMetadata
Ord, (forall x. AssetMetadata -> Rep AssetMetadata x)
-> (forall x. Rep AssetMetadata x -> AssetMetadata)
-> Generic AssetMetadata
forall x. Rep AssetMetadata x -> AssetMetadata
forall x. AssetMetadata -> Rep AssetMetadata x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep AssetMetadata x -> AssetMetadata
$cfrom :: forall x. AssetMetadata -> Rep AssetMetadata x
Generic)
    deriving (Int -> AssetMetadata -> ShowS
[AssetMetadata] -> ShowS
AssetMetadata -> String
(Int -> AssetMetadata -> ShowS)
-> (AssetMetadata -> String)
-> ([AssetMetadata] -> ShowS)
-> Show AssetMetadata
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AssetMetadata] -> ShowS
$cshowList :: [AssetMetadata] -> ShowS
show :: AssetMetadata -> String
$cshow :: AssetMetadata -> String
showsPrec :: Int -> AssetMetadata -> ShowS
$cshowsPrec :: Int -> AssetMetadata -> ShowS
Show) via (Quiet AssetMetadata)

instance NFData AssetMetadata

-- | Specify an asset logo as an image data payload
newtype  = 
    {  :: ByteString
    } deriving (AssetLogo -> AssetLogo -> Bool
(AssetLogo -> AssetLogo -> Bool)
-> (AssetLogo -> AssetLogo -> Bool) -> Eq AssetLogo
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AssetLogo -> AssetLogo -> Bool
$c/= :: AssetLogo -> AssetLogo -> Bool
== :: AssetLogo -> AssetLogo -> Bool
$c== :: AssetLogo -> AssetLogo -> Bool
Eq, Eq AssetLogo
Eq AssetLogo
-> (AssetLogo -> AssetLogo -> Ordering)
-> (AssetLogo -> AssetLogo -> Bool)
-> (AssetLogo -> AssetLogo -> Bool)
-> (AssetLogo -> AssetLogo -> Bool)
-> (AssetLogo -> AssetLogo -> Bool)
-> (AssetLogo -> AssetLogo -> AssetLogo)
-> (AssetLogo -> AssetLogo -> AssetLogo)
-> Ord AssetLogo
AssetLogo -> AssetLogo -> Bool
AssetLogo -> AssetLogo -> Ordering
AssetLogo -> AssetLogo -> AssetLogo
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 :: AssetLogo -> AssetLogo -> AssetLogo
$cmin :: AssetLogo -> AssetLogo -> AssetLogo
max :: AssetLogo -> AssetLogo -> AssetLogo
$cmax :: AssetLogo -> AssetLogo -> AssetLogo
>= :: AssetLogo -> AssetLogo -> Bool
$c>= :: AssetLogo -> AssetLogo -> Bool
> :: AssetLogo -> AssetLogo -> Bool
$c> :: AssetLogo -> AssetLogo -> Bool
<= :: AssetLogo -> AssetLogo -> Bool
$c<= :: AssetLogo -> AssetLogo -> Bool
< :: AssetLogo -> AssetLogo -> Bool
$c< :: AssetLogo -> AssetLogo -> Bool
compare :: AssetLogo -> AssetLogo -> Ordering
$ccompare :: AssetLogo -> AssetLogo -> Ordering
$cp1Ord :: Eq AssetLogo
Ord, (forall x. AssetLogo -> Rep AssetLogo x)
-> (forall x. Rep AssetLogo x -> AssetLogo) -> Generic AssetLogo
forall x. Rep AssetLogo x -> AssetLogo
forall x. AssetLogo -> Rep AssetLogo x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep AssetLogo x -> AssetLogo
$cfrom :: forall x. AssetLogo -> Rep AssetLogo x
Generic)
    deriving (Int -> AssetLogo -> ShowS
[AssetLogo] -> ShowS
AssetLogo -> String
(Int -> AssetLogo -> ShowS)
-> (AssetLogo -> String)
-> ([AssetLogo] -> ShowS)
-> Show AssetLogo
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AssetLogo] -> ShowS
$cshowList :: [AssetLogo] -> ShowS
show :: AssetLogo -> String
$cshow :: AssetLogo -> String
showsPrec :: Int -> AssetLogo -> ShowS
$cshowsPrec :: Int -> AssetLogo -> ShowS
Show) via (Quiet AssetLogo)

instance NFData AssetLogo

-- | The validated URL for the asset.
newtype AssetURL = AssetURL
    { AssetURL -> URI
unAssetURL :: URI
    } deriving (AssetURL -> AssetURL -> Bool
(AssetURL -> AssetURL -> Bool)
-> (AssetURL -> AssetURL -> Bool) -> Eq AssetURL
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AssetURL -> AssetURL -> Bool
$c/= :: AssetURL -> AssetURL -> Bool
== :: AssetURL -> AssetURL -> Bool
$c== :: AssetURL -> AssetURL -> Bool
Eq, Eq AssetURL
Eq AssetURL
-> (AssetURL -> AssetURL -> Ordering)
-> (AssetURL -> AssetURL -> Bool)
-> (AssetURL -> AssetURL -> Bool)
-> (AssetURL -> AssetURL -> Bool)
-> (AssetURL -> AssetURL -> Bool)
-> (AssetURL -> AssetURL -> AssetURL)
-> (AssetURL -> AssetURL -> AssetURL)
-> Ord AssetURL
AssetURL -> AssetURL -> Bool
AssetURL -> AssetURL -> Ordering
AssetURL -> AssetURL -> AssetURL
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 :: AssetURL -> AssetURL -> AssetURL
$cmin :: AssetURL -> AssetURL -> AssetURL
max :: AssetURL -> AssetURL -> AssetURL
$cmax :: AssetURL -> AssetURL -> AssetURL
>= :: AssetURL -> AssetURL -> Bool
$c>= :: AssetURL -> AssetURL -> Bool
> :: AssetURL -> AssetURL -> Bool
$c> :: AssetURL -> AssetURL -> Bool
<= :: AssetURL -> AssetURL -> Bool
$c<= :: AssetURL -> AssetURL -> Bool
< :: AssetURL -> AssetURL -> Bool
$c< :: AssetURL -> AssetURL -> Bool
compare :: AssetURL -> AssetURL -> Ordering
$ccompare :: AssetURL -> AssetURL -> Ordering
$cp1Ord :: Eq AssetURL
Ord, (forall x. AssetURL -> Rep AssetURL x)
-> (forall x. Rep AssetURL x -> AssetURL) -> Generic AssetURL
forall x. Rep AssetURL x -> AssetURL
forall x. AssetURL -> Rep AssetURL x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep AssetURL x -> AssetURL
$cfrom :: forall x. AssetURL -> Rep AssetURL x
Generic)
    deriving (Int -> AssetURL -> ShowS
[AssetURL] -> ShowS
AssetURL -> String
(Int -> AssetURL -> ShowS)
-> (AssetURL -> String) -> ([AssetURL] -> ShowS) -> Show AssetURL
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AssetURL] -> ShowS
$cshowList :: [AssetURL] -> ShowS
show :: AssetURL -> String
$cshow :: AssetURL -> String
showsPrec :: Int -> AssetURL -> ShowS
$cshowsPrec :: Int -> AssetURL -> ShowS
Show) via (Quiet AssetURL)

instance NFData AssetURL

instance ToText AssetURL where
    toText :: AssetURL -> Text
toText = String -> Text
T.pack (String -> Text) -> (AssetURL -> String) -> AssetURL -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. URI -> String
forall a. Show a => a -> String
show (URI -> String) -> (AssetURL -> URI) -> AssetURL -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AssetURL -> URI
unAssetURL

instance FromText AssetURL where
    fromText :: Text -> Either TextDecodingError AssetURL
fromText = (String -> TextDecodingError)
-> Either String AssetURL -> Either TextDecodingError AssetURL
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first String -> TextDecodingError
TextDecodingError (Either String AssetURL -> Either TextDecodingError AssetURL)
-> (Text -> Either String AssetURL)
-> Text
-> Either TextDecodingError AssetURL
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Either String AssetURL
validateMetadataURL

newtype AssetDecimals = AssetDecimals
  { AssetDecimals -> Int
unAssetDecimals :: Int
  } deriving (AssetDecimals -> AssetDecimals -> Bool
(AssetDecimals -> AssetDecimals -> Bool)
-> (AssetDecimals -> AssetDecimals -> Bool) -> Eq AssetDecimals
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AssetDecimals -> AssetDecimals -> Bool
$c/= :: AssetDecimals -> AssetDecimals -> Bool
== :: AssetDecimals -> AssetDecimals -> Bool
$c== :: AssetDecimals -> AssetDecimals -> Bool
Eq, Eq AssetDecimals
Eq AssetDecimals
-> (AssetDecimals -> AssetDecimals -> Ordering)
-> (AssetDecimals -> AssetDecimals -> Bool)
-> (AssetDecimals -> AssetDecimals -> Bool)
-> (AssetDecimals -> AssetDecimals -> Bool)
-> (AssetDecimals -> AssetDecimals -> Bool)
-> (AssetDecimals -> AssetDecimals -> AssetDecimals)
-> (AssetDecimals -> AssetDecimals -> AssetDecimals)
-> Ord AssetDecimals
AssetDecimals -> AssetDecimals -> Bool
AssetDecimals -> AssetDecimals -> Ordering
AssetDecimals -> AssetDecimals -> AssetDecimals
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 :: AssetDecimals -> AssetDecimals -> AssetDecimals
$cmin :: AssetDecimals -> AssetDecimals -> AssetDecimals
max :: AssetDecimals -> AssetDecimals -> AssetDecimals
$cmax :: AssetDecimals -> AssetDecimals -> AssetDecimals
>= :: AssetDecimals -> AssetDecimals -> Bool
$c>= :: AssetDecimals -> AssetDecimals -> Bool
> :: AssetDecimals -> AssetDecimals -> Bool
$c> :: AssetDecimals -> AssetDecimals -> Bool
<= :: AssetDecimals -> AssetDecimals -> Bool
$c<= :: AssetDecimals -> AssetDecimals -> Bool
< :: AssetDecimals -> AssetDecimals -> Bool
$c< :: AssetDecimals -> AssetDecimals -> Bool
compare :: AssetDecimals -> AssetDecimals -> Ordering
$ccompare :: AssetDecimals -> AssetDecimals -> Ordering
$cp1Ord :: Eq AssetDecimals
Ord, (forall x. AssetDecimals -> Rep AssetDecimals x)
-> (forall x. Rep AssetDecimals x -> AssetDecimals)
-> Generic AssetDecimals
forall x. Rep AssetDecimals x -> AssetDecimals
forall x. AssetDecimals -> Rep AssetDecimals x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep AssetDecimals x -> AssetDecimals
$cfrom :: forall x. AssetDecimals -> Rep AssetDecimals x
Generic)
  deriving (Int -> AssetDecimals -> ShowS
[AssetDecimals] -> ShowS
AssetDecimals -> String
(Int -> AssetDecimals -> ShowS)
-> (AssetDecimals -> String)
-> ([AssetDecimals] -> ShowS)
-> Show AssetDecimals
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AssetDecimals] -> ShowS
$cshowList :: [AssetDecimals] -> ShowS
show :: AssetDecimals -> String
$cshow :: AssetDecimals -> String
showsPrec :: Int -> AssetDecimals -> ShowS
$cshowsPrec :: Int -> AssetDecimals -> ShowS
Show) via (Quiet AssetDecimals)

instance NFData AssetDecimals

instance ToText AssetDecimals where
  toText :: AssetDecimals -> Text
toText = String -> Text
T.pack (String -> Text)
-> (AssetDecimals -> String) -> AssetDecimals -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String
forall a. Show a => a -> String
show (Int -> String)
-> (AssetDecimals -> Int) -> AssetDecimals -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AssetDecimals -> Int
unAssetDecimals

instance FromText AssetDecimals where
  fromText :: Text -> Either TextDecodingError AssetDecimals
fromText Text
t = do
    AssetDecimals
unvalidated <- Int -> AssetDecimals
AssetDecimals (Int -> AssetDecimals)
-> Either TextDecodingError Int
-> Either TextDecodingError AssetDecimals
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Either TextDecodingError Int
forall a. FromText a => Text -> Either TextDecodingError a
fromText Text
t
    (String -> TextDecodingError)
-> Either String AssetDecimals
-> Either TextDecodingError AssetDecimals
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first String -> TextDecodingError
TextDecodingError (Either String AssetDecimals
 -> Either TextDecodingError AssetDecimals)
-> Either String AssetDecimals
-> Either TextDecodingError AssetDecimals
forall a b. (a -> b) -> a -> b
$ AssetDecimals -> Either String AssetDecimals
validateMetadataDecimals AssetDecimals
unvalidated

validateMinLength :: Int -> Text -> Either String Text
validateMinLength :: Int -> Text -> Either String Text
validateMinLength Int
n Text
text
    | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
n = Text -> Either String Text
forall a b. b -> Either a b
Right Text
text
    | Bool
otherwise = String -> Either String Text
forall a b. a -> Either a b
Left (String -> Either String Text) -> String -> Either String Text
forall a b. (a -> b) -> a -> b
$ String
"Length must be at least " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
n String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" characters, got " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
len
  where
    len :: Int
len = Text -> Int
T.length Text
text

validateMaxLength :: Int -> Text -> Either String Text
validateMaxLength :: Int -> Text -> Either String Text
validateMaxLength Int
n Text
text
    | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
n = Text -> Either String Text
forall a b. b -> Either a b
Right Text
text
    | Bool
otherwise = String -> Either String Text
forall a b. a -> Either a b
Left (String -> Either String Text) -> String -> Either String Text
forall a b. (a -> b) -> a -> b
$ String
"Length must be no more than " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
n String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" characters, got " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
len
  where
    len :: Int
len = Text -> Int
T.length Text
text

validateMetadataName :: Text -> Either String Text
validateMetadataName :: Text -> Either String Text
validateMetadataName = Int -> Text -> Either String Text
validateMinLength Int
1 (Text -> Either String Text)
-> (Text -> Either String Text) -> Text -> Either String Text
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> Int -> Text -> Either String Text
validateMaxLength Int
50

validateMetadataTicker :: Text -> Either String Text
validateMetadataTicker :: Text -> Either String Text
validateMetadataTicker = Int -> Text -> Either String Text
validateMinLength Int
2 (Text -> Either String Text)
-> (Text -> Either String Text) -> Text -> Either String Text
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> Int -> Text -> Either String Text
validateMaxLength Int
6

validateMetadataDescription :: Text -> Either String Text
validateMetadataDescription :: Text -> Either String Text
validateMetadataDescription = Int -> Text -> Either String Text
validateMaxLength Int
500

validateMetadataURL :: Text -> Either String AssetURL
validateMetadataURL :: Text -> Either String AssetURL
validateMetadataURL = (URI -> AssetURL) -> Either String URI -> Either String AssetURL
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap URI -> AssetURL
AssetURL (Either String URI -> Either String AssetURL)
-> (Text -> Either String URI) -> Text -> Either String AssetURL
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
    (Int -> Text -> Either String Text
validateMaxLength Int
250 (Text -> Either String Text)
-> (Text -> Either String URI) -> Text -> Either String URI
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> Text -> Either String URI
validateURI (Text -> Either String URI)
-> (URI -> Either String URI) -> Text -> Either String URI
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> URI -> Either String URI
validateHttps)
  where
      validateURI :: Text -> Either String URI
validateURI = Either String URI
-> (URI -> Either String URI) -> Maybe URI -> Either String URI
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (String -> Either String URI
forall a b. a -> Either a b
Left String
"Not an absolute URI") URI -> Either String URI
forall a b. b -> Either a b
Right
          (Maybe URI -> Either String URI)
-> (Text -> Maybe URI) -> Text -> Either String URI
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Maybe URI
parseAbsoluteURI
          (String -> Maybe URI) -> (Text -> String) -> Text -> Maybe URI
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack
      validateHttps :: URI -> Either String URI
validateHttps u :: URI
u@(URI -> String
uriScheme -> String
scheme)
          | String
scheme String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"https:" = URI -> Either String URI
forall a b. b -> Either a b
Right URI
u
          | Bool
otherwise = String -> Either String URI
forall a b. a -> Either a b
Left (String -> Either String URI) -> String -> Either String URI
forall a b. (a -> b) -> a -> b
$ String
"Scheme must be https: but got " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
scheme

validateMetadataLogo :: AssetLogo -> Either String AssetLogo
 AssetLogo
logo
    | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
maxLen = AssetLogo -> Either String AssetLogo
forall a b. b -> Either a b
Right AssetLogo
logo
    | Bool
otherwise = String -> Either String AssetLogo
forall a b. a -> Either a b
Left (String -> Either String AssetLogo)
-> String -> Either String AssetLogo
forall a b. (a -> b) -> a -> b
$ String
"Length must be no more than " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
maxLen String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" bytes, got " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
len
  where
    len :: Int
len = ByteString -> Int
BS.length (ByteString -> Int) -> ByteString -> Int
forall a b. (a -> b) -> a -> b
$ AssetLogo -> ByteString
unAssetLogo AssetLogo
logo
    maxLen :: Int
maxLen = Int
65536

validateMetadataDecimals :: AssetDecimals -> Either String AssetDecimals
validateMetadataDecimals :: AssetDecimals -> Either String AssetDecimals
validateMetadataDecimals (AssetDecimals Int
n)
  | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
255 = AssetDecimals -> Either String AssetDecimals
forall a b. b -> Either a b
Right (AssetDecimals -> Either String AssetDecimals)
-> AssetDecimals -> Either String AssetDecimals
forall a b. (a -> b) -> a -> b
$ Int -> AssetDecimals
AssetDecimals Int
n
  | Bool
otherwise          = String -> Either String AssetDecimals
forall a b. a -> Either a b
Left String
"Decimal value must be between [0, 255] inclusive."