{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Bcc.CLI.Sophie.Run.Address
  ( SophieAddressCmdError(..)
  , SomeAddressVerificationKey(..)
  , buildSophieAddress
  , renderSophieAddressCmdError
  , runAddressCmd
  , runAddressKeyGen
  , readAddressVerificationKeyTextOrFile
  ) where

import           Bcc.Prelude hiding (putStrLn)


import qualified Data.ByteString.Char8 as BS
import qualified Data.Text as Text
import qualified Data.Text.IO as Text

import           Control.Monad.Trans.Except.Extra (firstExceptT, newExceptT)

import           Bcc.Api
import           Bcc.Api.Sophie

import           Bcc.CLI.Helpers
import           Bcc.CLI.Sophie.Key (InputDecodeError, PaymentVerifier (..),
                   StakeVerifier (..), VerificationKeyTextOrFile,
                   VerificationKeyTextOrFileError (..), readVerificationKeyOrFile,
                   readVerificationKeyTextOrFileAnyOf, renderVerificationKeyTextOrFileError)
import           Bcc.CLI.Sophie.Parsers (AddressCmd (..), AddressKeyType (..), OutputFile (..))
import           Bcc.CLI.Sophie.Run.Address.Info (SophieAddressInfoError, runAddressInfo)
import           Bcc.CLI.Sophie.Script
import           Bcc.CLI.Types

data SophieAddressCmdError
  = SophieAddressCmdAddressInfoError !SophieAddressInfoError
  | SophieAddressCmdReadKeyFileError !(FileError InputDecodeError)
  | SophieAddressCmdReadScriptFileError !(FileError ScriptDecodeError)
  | SophieAddressCmdVerificationKeyTextOrFileError !VerificationKeyTextOrFileError
  | SophieAddressCmdWriteFileError !(FileError ())
  deriving Int -> SophieAddressCmdError -> ShowS
[SophieAddressCmdError] -> ShowS
SophieAddressCmdError -> String
(Int -> SophieAddressCmdError -> ShowS)
-> (SophieAddressCmdError -> String)
-> ([SophieAddressCmdError] -> ShowS)
-> Show SophieAddressCmdError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SophieAddressCmdError] -> ShowS
$cshowList :: [SophieAddressCmdError] -> ShowS
show :: SophieAddressCmdError -> String
$cshow :: SophieAddressCmdError -> String
showsPrec :: Int -> SophieAddressCmdError -> ShowS
$cshowsPrec :: Int -> SophieAddressCmdError -> ShowS
Show

renderSophieAddressCmdError :: SophieAddressCmdError -> Text
renderSophieAddressCmdError :: SophieAddressCmdError -> Text
renderSophieAddressCmdError SophieAddressCmdError
err =
  case SophieAddressCmdError
err of
    SophieAddressCmdAddressInfoError SophieAddressInfoError
addrInfoErr ->
      String -> Text
Text.pack (SophieAddressInfoError -> String
forall e. Error e => e -> String
displayError SophieAddressInfoError
addrInfoErr)
    SophieAddressCmdReadKeyFileError FileError InputDecodeError
fileErr ->
      String -> Text
Text.pack (FileError InputDecodeError -> String
forall e. Error e => e -> String
displayError FileError InputDecodeError
fileErr)
    SophieAddressCmdVerificationKeyTextOrFileError VerificationKeyTextOrFileError
vkTextOrFileErr ->
      VerificationKeyTextOrFileError -> Text
renderVerificationKeyTextOrFileError VerificationKeyTextOrFileError
vkTextOrFileErr
    SophieAddressCmdReadScriptFileError FileError ScriptDecodeError
fileErr ->
      String -> Text
Text.pack (FileError ScriptDecodeError -> String
forall e. Error e => e -> String
displayError FileError ScriptDecodeError
fileErr)
    SophieAddressCmdWriteFileError FileError ()
fileErr -> String -> Text
Text.pack (FileError () -> String
forall e. Error e => e -> String
displayError FileError ()
fileErr)

runAddressCmd :: AddressCmd -> ExceptT SophieAddressCmdError IO ()
runAddressCmd :: AddressCmd -> ExceptT SophieAddressCmdError IO ()
runAddressCmd AddressCmd
cmd =
  case AddressCmd
cmd of
    AddressKeyGen AddressKeyType
kt VerificationKeyFile
vkf SigningKeyFile
skf -> AddressKeyType
-> VerificationKeyFile
-> SigningKeyFile
-> ExceptT SophieAddressCmdError IO ()
runAddressKeyGen AddressKeyType
kt VerificationKeyFile
vkf SigningKeyFile
skf
    AddressKeyHash VerificationKeyTextOrFile
vkf Maybe OutputFile
mOFp -> VerificationKeyTextOrFile
-> Maybe OutputFile -> ExceptT SophieAddressCmdError IO ()
runAddressKeyHash VerificationKeyTextOrFile
vkf Maybe OutputFile
mOFp
    AddressBuild PaymentVerifier
paymentVerifier Maybe StakeVerifier
mbStakeVerifier NetworkId
nw Maybe OutputFile
mOutFp -> PaymentVerifier
-> Maybe StakeVerifier
-> NetworkId
-> Maybe OutputFile
-> ExceptT SophieAddressCmdError IO ()
runAddressBuild PaymentVerifier
paymentVerifier Maybe StakeVerifier
mbStakeVerifier NetworkId
nw Maybe OutputFile
mOutFp
    AddressBuildMultiSig ScriptFile
sFp NetworkId
nId Maybe OutputFile
mOutFp -> ScriptFile
-> NetworkId
-> Maybe OutputFile
-> ExceptT SophieAddressCmdError IO ()
runAddressBuildScript ScriptFile
sFp NetworkId
nId Maybe OutputFile
mOutFp
    AddressInfo Text
txt Maybe OutputFile
mOFp -> (SophieAddressInfoError -> SophieAddressCmdError)
-> ExceptT SophieAddressInfoError IO ()
-> ExceptT SophieAddressCmdError IO ()
forall (m :: * -> *) x y a.
Functor m =>
(x -> y) -> ExceptT x m a -> ExceptT y m a
firstExceptT SophieAddressInfoError -> SophieAddressCmdError
SophieAddressCmdAddressInfoError (ExceptT SophieAddressInfoError IO ()
 -> ExceptT SophieAddressCmdError IO ())
-> ExceptT SophieAddressInfoError IO ()
-> ExceptT SophieAddressCmdError IO ()
forall a b. (a -> b) -> a -> b
$ Text -> Maybe OutputFile -> ExceptT SophieAddressInfoError IO ()
runAddressInfo Text
txt Maybe OutputFile
mOFp

runAddressKeyGen :: AddressKeyType
                 -> VerificationKeyFile
                 -> SigningKeyFile
                 -> ExceptT SophieAddressCmdError IO ()
runAddressKeyGen :: AddressKeyType
-> VerificationKeyFile
-> SigningKeyFile
-> ExceptT SophieAddressCmdError IO ()
runAddressKeyGen AddressKeyType
kt (VerificationKeyFile String
vkeyPath) (SigningKeyFile String
skeyPath) =
    case AddressKeyType
kt of
      AddressKeyType
AddressKeySophie         -> AsType PaymentKey -> ExceptT SophieAddressCmdError IO ()
forall keyrole.
Key keyrole =>
AsType keyrole -> ExceptT SophieAddressCmdError IO ()
generateAndWriteKeyFiles AsType PaymentKey
AsPaymentKey
      AddressKeyType
AddressKeySophieExtended -> AsType PaymentExtendedKey -> ExceptT SophieAddressCmdError IO ()
forall keyrole.
Key keyrole =>
AsType keyrole -> ExceptT SophieAddressCmdError IO ()
generateAndWriteKeyFiles AsType PaymentExtendedKey
AsPaymentExtendedKey
      AddressKeyType
AddressKeyCole           -> AsType ColeKey -> ExceptT SophieAddressCmdError IO ()
forall keyrole.
Key keyrole =>
AsType keyrole -> ExceptT SophieAddressCmdError IO ()
generateAndWriteKeyFiles AsType ColeKey
AsColeKey
  where
    generateAndWriteKeyFiles :: AsType keyrole -> ExceptT SophieAddressCmdError IO ()
generateAndWriteKeyFiles AsType keyrole
asType = do
      SigningKey keyrole
skey <- IO (SigningKey keyrole)
-> ExceptT SophieAddressCmdError IO (SigningKey keyrole)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (SigningKey keyrole)
 -> ExceptT SophieAddressCmdError IO (SigningKey keyrole))
-> IO (SigningKey keyrole)
-> ExceptT SophieAddressCmdError IO (SigningKey keyrole)
forall a b. (a -> b) -> a -> b
$ AsType keyrole -> IO (SigningKey keyrole)
forall keyrole.
Key keyrole =>
AsType keyrole -> IO (SigningKey keyrole)
generateSigningKey AsType keyrole
asType
      let vkey :: VerificationKey keyrole
vkey = SigningKey keyrole -> VerificationKey keyrole
forall keyrole.
Key keyrole =>
SigningKey keyrole -> VerificationKey keyrole
getVerificationKey SigningKey keyrole
skey
      (FileError () -> SophieAddressCmdError)
-> ExceptT (FileError ()) IO ()
-> ExceptT SophieAddressCmdError IO ()
forall (m :: * -> *) x y a.
Functor m =>
(x -> y) -> ExceptT x m a -> ExceptT y m a
firstExceptT FileError () -> SophieAddressCmdError
SophieAddressCmdWriteFileError
        (ExceptT (FileError ()) IO ()
 -> ExceptT SophieAddressCmdError IO ())
-> (IO (Either (FileError ()) ()) -> ExceptT (FileError ()) IO ())
-> IO (Either (FileError ()) ())
-> ExceptT SophieAddressCmdError IO ()
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. IO (Either (FileError ()) ()) -> ExceptT (FileError ()) IO ()
forall (m :: * -> *) x a. m (Either x a) -> ExceptT x m a
newExceptT
        (IO (Either (FileError ()) ())
 -> ExceptT SophieAddressCmdError IO ())
-> IO (Either (FileError ()) ())
-> ExceptT SophieAddressCmdError IO ()
forall a b. (a -> b) -> a -> b
$ String
-> Maybe TextEnvelopeDescr
-> SigningKey keyrole
-> IO (Either (FileError ()) ())
forall a.
HasTextEnvelope a =>
String
-> Maybe TextEnvelopeDescr -> a -> IO (Either (FileError ()) ())
writeFileTextEnvelope String
skeyPath (TextEnvelopeDescr -> Maybe TextEnvelopeDescr
forall a. a -> Maybe a
Just TextEnvelopeDescr
skeyDesc) SigningKey keyrole
skey
      (FileError () -> SophieAddressCmdError)
-> ExceptT (FileError ()) IO ()
-> ExceptT SophieAddressCmdError IO ()
forall (m :: * -> *) x y a.
Functor m =>
(x -> y) -> ExceptT x m a -> ExceptT y m a
firstExceptT FileError () -> SophieAddressCmdError
SophieAddressCmdWriteFileError
        (ExceptT (FileError ()) IO ()
 -> ExceptT SophieAddressCmdError IO ())
-> (IO (Either (FileError ()) ()) -> ExceptT (FileError ()) IO ())
-> IO (Either (FileError ()) ())
-> ExceptT SophieAddressCmdError IO ()
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. IO (Either (FileError ()) ()) -> ExceptT (FileError ()) IO ()
forall (m :: * -> *) x a. m (Either x a) -> ExceptT x m a
newExceptT
        (IO (Either (FileError ()) ())
 -> ExceptT SophieAddressCmdError IO ())
-> IO (Either (FileError ()) ())
-> ExceptT SophieAddressCmdError IO ()
forall a b. (a -> b) -> a -> b
$ String
-> Maybe TextEnvelopeDescr
-> VerificationKey keyrole
-> IO (Either (FileError ()) ())
forall a.
HasTextEnvelope a =>
String
-> Maybe TextEnvelopeDescr -> a -> IO (Either (FileError ()) ())
writeFileTextEnvelope String
vkeyPath (TextEnvelopeDescr -> Maybe TextEnvelopeDescr
forall a. a -> Maybe a
Just TextEnvelopeDescr
vkeyDesc) VerificationKey keyrole
vkey

    skeyDesc, vkeyDesc :: TextEnvelopeDescr
    skeyDesc :: TextEnvelopeDescr
skeyDesc = TextEnvelopeDescr
"Payment Signing Key"
    vkeyDesc :: TextEnvelopeDescr
vkeyDesc = TextEnvelopeDescr
"Payment Verification Key"


runAddressKeyHash :: VerificationKeyTextOrFile
                  -> Maybe OutputFile
                  -> ExceptT SophieAddressCmdError IO ()
runAddressKeyHash :: VerificationKeyTextOrFile
-> Maybe OutputFile -> ExceptT SophieAddressCmdError IO ()
runAddressKeyHash VerificationKeyTextOrFile
vkeyTextOrFile Maybe OutputFile
mOutputFp = do
  SomeAddressVerificationKey
vkey <- (VerificationKeyTextOrFileError -> SophieAddressCmdError)
-> ExceptT
     VerificationKeyTextOrFileError IO SomeAddressVerificationKey
-> ExceptT SophieAddressCmdError IO SomeAddressVerificationKey
forall (m :: * -> *) x y a.
Functor m =>
(x -> y) -> ExceptT x m a -> ExceptT y m a
firstExceptT VerificationKeyTextOrFileError -> SophieAddressCmdError
SophieAddressCmdVerificationKeyTextOrFileError (ExceptT
   VerificationKeyTextOrFileError IO SomeAddressVerificationKey
 -> ExceptT SophieAddressCmdError IO SomeAddressVerificationKey)
-> ExceptT
     VerificationKeyTextOrFileError IO SomeAddressVerificationKey
-> ExceptT SophieAddressCmdError IO SomeAddressVerificationKey
forall a b. (a -> b) -> a -> b
$
            VerificationKeyTextOrFile
-> ExceptT
     VerificationKeyTextOrFileError IO SomeAddressVerificationKey
readAddressVerificationKeyTextOrFile VerificationKeyTextOrFile
vkeyTextOrFile

  let hexKeyHash :: ByteString
hexKeyHash = (forall keyrole.
 Key keyrole =>
 VerificationKey keyrole -> ByteString)
-> SomeAddressVerificationKey -> ByteString
forall a.
(forall keyrole. Key keyrole => VerificationKey keyrole -> a)
-> SomeAddressVerificationKey -> a
foldSomeAddressVerificationKey
                     (Hash keyrole -> ByteString
forall a. SerialiseAsRawBytes a => a -> ByteString
serialiseToRawBytesHex (Hash keyrole -> ByteString)
-> (VerificationKey keyrole -> Hash keyrole)
-> VerificationKey keyrole
-> ByteString
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. VerificationKey keyrole -> Hash keyrole
forall keyrole.
Key keyrole =>
VerificationKey keyrole -> Hash keyrole
verificationKeyHash) SomeAddressVerificationKey
vkey

  case Maybe OutputFile
mOutputFp of
    Just (OutputFile String
fpath) -> IO () -> ExceptT SophieAddressCmdError IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ExceptT SophieAddressCmdError IO ())
-> IO () -> ExceptT SophieAddressCmdError IO ()
forall a b. (a -> b) -> a -> b
$ String -> ByteString -> IO ()
BS.writeFile String
fpath ByteString
hexKeyHash
    Maybe OutputFile
Nothing -> IO () -> ExceptT SophieAddressCmdError IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ExceptT SophieAddressCmdError IO ())
-> IO () -> ExceptT SophieAddressCmdError IO ()
forall a b. (a -> b) -> a -> b
$ ByteString -> IO ()
BS.putStrLn ByteString
hexKeyHash


runAddressBuild :: PaymentVerifier
                -> Maybe StakeVerifier
                -> NetworkId
                -> Maybe OutputFile
                -> ExceptT SophieAddressCmdError IO ()
runAddressBuild :: PaymentVerifier
-> Maybe StakeVerifier
-> NetworkId
-> Maybe OutputFile
-> ExceptT SophieAddressCmdError IO ()
runAddressBuild PaymentVerifier
paymentVerifier Maybe StakeVerifier
mbStakeVerifier NetworkId
nw Maybe OutputFile
mOutFp = do
  Text
outText <- case PaymentVerifier
paymentVerifier of
    PaymentVerifierKey VerificationKeyTextOrFile
payVkeyTextOrFile -> do
      SomeAddressVerificationKey
payVKey <- (VerificationKeyTextOrFileError -> SophieAddressCmdError)
-> ExceptT
     VerificationKeyTextOrFileError IO SomeAddressVerificationKey
-> ExceptT SophieAddressCmdError IO SomeAddressVerificationKey
forall (m :: * -> *) x y a.
Functor m =>
(x -> y) -> ExceptT x m a -> ExceptT y m a
firstExceptT VerificationKeyTextOrFileError -> SophieAddressCmdError
SophieAddressCmdVerificationKeyTextOrFileError (ExceptT
   VerificationKeyTextOrFileError IO SomeAddressVerificationKey
 -> ExceptT SophieAddressCmdError IO SomeAddressVerificationKey)
-> ExceptT
     VerificationKeyTextOrFileError IO SomeAddressVerificationKey
-> ExceptT SophieAddressCmdError IO SomeAddressVerificationKey
forall a b. (a -> b) -> a -> b
$
        VerificationKeyTextOrFile
-> ExceptT
     VerificationKeyTextOrFileError IO SomeAddressVerificationKey
readAddressVerificationKeyTextOrFile VerificationKeyTextOrFile
payVkeyTextOrFile

      AddressAny
addr <- case SomeAddressVerificationKey
payVKey of
        AColeVerificationKey VerificationKey ColeKey
vk ->
          AddressAny -> ExceptT SophieAddressCmdError IO AddressAny
forall (m :: * -> *) a. Monad m => a -> m a
return (Address ColeAddr -> AddressAny
AddressCole (NetworkId -> VerificationKey ColeKey -> Address ColeAddr
makeColeAddress NetworkId
nw VerificationKey ColeKey
vk))

        APaymentVerificationKey VerificationKey PaymentKey
vk ->
          Address SophieAddr -> AddressAny
AddressSophie (Address SophieAddr -> AddressAny)
-> ExceptT SophieAddressCmdError IO (Address SophieAddr)
-> ExceptT SophieAddressCmdError IO AddressAny
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> VerificationKey PaymentKey
-> Maybe StakeVerifier
-> NetworkId
-> ExceptT SophieAddressCmdError IO (Address SophieAddr)
buildSophieAddress VerificationKey PaymentKey
vk Maybe StakeVerifier
mbStakeVerifier NetworkId
nw

        APaymentExtendedVerificationKey VerificationKey PaymentExtendedKey
vk ->
          Address SophieAddr -> AddressAny
AddressSophie (Address SophieAddr -> AddressAny)
-> ExceptT SophieAddressCmdError IO (Address SophieAddr)
-> ExceptT SophieAddressCmdError IO AddressAny
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> VerificationKey PaymentKey
-> Maybe StakeVerifier
-> NetworkId
-> ExceptT SophieAddressCmdError IO (Address SophieAddr)
buildSophieAddress (VerificationKey PaymentExtendedKey -> VerificationKey PaymentKey
forall keyroleA keyroleB.
CastVerificationKeyRole keyroleA keyroleB =>
VerificationKey keyroleA -> VerificationKey keyroleB
castVerificationKey VerificationKey PaymentExtendedKey
vk) Maybe StakeVerifier
mbStakeVerifier NetworkId
nw

        AGenesisUTxOVerificationKey VerificationKey GenesisUTxOKey
vk ->
          Address SophieAddr -> AddressAny
AddressSophie (Address SophieAddr -> AddressAny)
-> ExceptT SophieAddressCmdError IO (Address SophieAddr)
-> ExceptT SophieAddressCmdError IO AddressAny
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> VerificationKey PaymentKey
-> Maybe StakeVerifier
-> NetworkId
-> ExceptT SophieAddressCmdError IO (Address SophieAddr)
buildSophieAddress (VerificationKey GenesisUTxOKey -> VerificationKey PaymentKey
forall keyroleA keyroleB.
CastVerificationKeyRole keyroleA keyroleB =>
VerificationKey keyroleA -> VerificationKey keyroleB
castVerificationKey VerificationKey GenesisUTxOKey
vk) Maybe StakeVerifier
mbStakeVerifier NetworkId
nw

      Text -> ExceptT SophieAddressCmdError IO Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> ExceptT SophieAddressCmdError IO Text)
-> Text -> ExceptT SophieAddressCmdError IO Text
forall a b. (a -> b) -> a -> b
$ AddressAny -> Text
forall addr. SerialiseAddress addr => addr -> Text
serialiseAddress (AddressAny
addr :: AddressAny)

    PaymentVerifierScriptFile (ScriptFile String
fp) -> do
      ScriptInAnyLang ScriptLanguage lang
_lang Script lang
script <-
        (FileError ScriptDecodeError -> SophieAddressCmdError)
-> ExceptT (FileError ScriptDecodeError) IO ScriptInAnyLang
-> ExceptT SophieAddressCmdError IO ScriptInAnyLang
forall (m :: * -> *) x y a.
Functor m =>
(x -> y) -> ExceptT x m a -> ExceptT y m a
firstExceptT FileError ScriptDecodeError -> SophieAddressCmdError
SophieAddressCmdReadScriptFileError (ExceptT (FileError ScriptDecodeError) IO ScriptInAnyLang
 -> ExceptT SophieAddressCmdError IO ScriptInAnyLang)
-> ExceptT (FileError ScriptDecodeError) IO ScriptInAnyLang
-> ExceptT SophieAddressCmdError IO ScriptInAnyLang
forall a b. (a -> b) -> a -> b
$
          String -> ExceptT (FileError ScriptDecodeError) IO ScriptInAnyLang
readFileScriptInAnyLang String
fp

      let payCred :: PaymentCredential
payCred = ScriptHash -> PaymentCredential
PaymentCredentialByScript (Script lang -> ScriptHash
forall lang. Script lang -> ScriptHash
hashScript Script lang
script)

      Address SophieAddr -> Text
forall addr. SerialiseAddress addr => addr -> Text
serialiseAddress (Address SophieAddr -> Text)
-> (StakeAddressReference -> Address SophieAddr)
-> StakeAddressReference
-> Text
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. NetworkId
-> PaymentCredential -> StakeAddressReference -> Address SophieAddr
makeSophieAddress NetworkId
nw PaymentCredential
payCred (StakeAddressReference -> Text)
-> ExceptT SophieAddressCmdError IO StakeAddressReference
-> ExceptT SophieAddressCmdError IO Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe StakeVerifier
-> ExceptT SophieAddressCmdError IO StakeAddressReference
makeStakeAddressRef Maybe StakeVerifier
mbStakeVerifier

  case Maybe OutputFile
mOutFp of
    Just (OutputFile String
fpath) -> IO () -> ExceptT SophieAddressCmdError IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ExceptT SophieAddressCmdError IO ())
-> IO () -> ExceptT SophieAddressCmdError IO ()
forall a b. (a -> b) -> a -> b
$ String -> Text -> IO ()
Text.writeFile String
fpath Text
outText
    Maybe OutputFile
Nothing                 -> IO () -> ExceptT SophieAddressCmdError IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ExceptT SophieAddressCmdError IO ())
-> IO () -> ExceptT SophieAddressCmdError IO ()
forall a b. (a -> b) -> a -> b
$ Text -> IO ()
Text.putStr          Text
outText

makeStakeAddressRef
  :: Maybe StakeVerifier
  -> ExceptT SophieAddressCmdError IO StakeAddressReference
makeStakeAddressRef :: Maybe StakeVerifier
-> ExceptT SophieAddressCmdError IO StakeAddressReference
makeStakeAddressRef Maybe StakeVerifier
mbStakeVerifier = do
  case Maybe StakeVerifier
mbStakeVerifier of
    Maybe StakeVerifier
Nothing -> StakeAddressReference
-> ExceptT SophieAddressCmdError IO StakeAddressReference
forall (f :: * -> *) a. Applicative f => a -> f a
pure StakeAddressReference
NoStakeAddress
    Just StakeVerifier
stakeVerifier -> case StakeVerifier
stakeVerifier of
      StakeVerifierKey VerificationKeyOrFile StakeKey
stkVkeyOrFile -> do
        Maybe (VerificationKey StakeKey)
mstakeVKey <- (FileError InputDecodeError -> SophieAddressCmdError)
-> ExceptT
     (FileError InputDecodeError) IO (Maybe (VerificationKey StakeKey))
-> ExceptT
     SophieAddressCmdError IO (Maybe (VerificationKey StakeKey))
forall (m :: * -> *) x y a.
Functor m =>
(x -> y) -> ExceptT x m a -> ExceptT y m a
firstExceptT FileError InputDecodeError -> SophieAddressCmdError
SophieAddressCmdReadKeyFileError (ExceptT
   (FileError InputDecodeError) IO (Maybe (VerificationKey StakeKey))
 -> ExceptT
      SophieAddressCmdError IO (Maybe (VerificationKey StakeKey)))
-> ExceptT
     (FileError InputDecodeError) IO (Maybe (VerificationKey StakeKey))
-> ExceptT
     SophieAddressCmdError IO (Maybe (VerificationKey StakeKey))
forall a b. (a -> b) -> a -> b
$
          (VerificationKey StakeKey -> Maybe (VerificationKey StakeKey))
-> ExceptT
     (FileError InputDecodeError) IO (VerificationKey StakeKey)
-> ExceptT
     (FileError InputDecodeError) IO (Maybe (VerificationKey StakeKey))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap VerificationKey StakeKey -> Maybe (VerificationKey StakeKey)
forall a. a -> Maybe a
Just (ExceptT (FileError InputDecodeError) IO (VerificationKey StakeKey)
 -> ExceptT
      (FileError InputDecodeError) IO (Maybe (VerificationKey StakeKey)))
-> ExceptT
     (FileError InputDecodeError) IO (VerificationKey StakeKey)
-> ExceptT
     (FileError InputDecodeError) IO (Maybe (VerificationKey StakeKey))
forall a b. (a -> b) -> a -> b
$ IO (Either (FileError InputDecodeError) (VerificationKey StakeKey))
-> ExceptT
     (FileError InputDecodeError) IO (VerificationKey StakeKey)
forall (m :: * -> *) x a. m (Either x a) -> ExceptT x m a
newExceptT (IO
   (Either (FileError InputDecodeError) (VerificationKey StakeKey))
 -> ExceptT
      (FileError InputDecodeError) IO (VerificationKey StakeKey))
-> IO
     (Either (FileError InputDecodeError) (VerificationKey StakeKey))
-> ExceptT
     (FileError InputDecodeError) IO (VerificationKey StakeKey)
forall a b. (a -> b) -> a -> b
$ AsType StakeKey
-> VerificationKeyOrFile StakeKey
-> IO
     (Either (FileError InputDecodeError) (VerificationKey StakeKey))
forall keyrole.
(HasTextEnvelope (VerificationKey keyrole),
 SerialiseAsBech32 (VerificationKey keyrole)) =>
AsType keyrole
-> VerificationKeyOrFile keyrole
-> IO
     (Either (FileError InputDecodeError) (VerificationKey keyrole))
readVerificationKeyOrFile AsType StakeKey
AsStakeKey VerificationKeyOrFile StakeKey
stkVkeyOrFile

        StakeAddressReference
-> ExceptT SophieAddressCmdError IO StakeAddressReference
forall (m :: * -> *) a. Monad m => a -> m a
return (StakeAddressReference
 -> ExceptT SophieAddressCmdError IO StakeAddressReference)
-> StakeAddressReference
-> ExceptT SophieAddressCmdError IO StakeAddressReference
forall a b. (a -> b) -> a -> b
$ StakeAddressReference
-> (VerificationKey StakeKey -> StakeAddressReference)
-> Maybe (VerificationKey StakeKey)
-> StakeAddressReference
forall b a. b -> (a -> b) -> Maybe a -> b
maybe StakeAddressReference
NoStakeAddress
          (StakeCredential -> StakeAddressReference
StakeAddressByValue (StakeCredential -> StakeAddressReference)
-> (VerificationKey StakeKey -> StakeCredential)
-> VerificationKey StakeKey
-> StakeAddressReference
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Hash StakeKey -> StakeCredential
StakeCredentialByKey (Hash StakeKey -> StakeCredential)
-> (VerificationKey StakeKey -> Hash StakeKey)
-> VerificationKey StakeKey
-> StakeCredential
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. VerificationKey StakeKey -> Hash StakeKey
forall keyrole.
Key keyrole =>
VerificationKey keyrole -> Hash keyrole
verificationKeyHash)
          Maybe (VerificationKey StakeKey)
mstakeVKey

      StakeVerifierScriptFile (ScriptFile String
fp) -> do
        ScriptInAnyLang ScriptLanguage lang
_lang Script lang
script <-
          (FileError ScriptDecodeError -> SophieAddressCmdError)
-> ExceptT (FileError ScriptDecodeError) IO ScriptInAnyLang
-> ExceptT SophieAddressCmdError IO ScriptInAnyLang
forall (m :: * -> *) x y a.
Functor m =>
(x -> y) -> ExceptT x m a -> ExceptT y m a
firstExceptT FileError ScriptDecodeError -> SophieAddressCmdError
SophieAddressCmdReadScriptFileError (ExceptT (FileError ScriptDecodeError) IO ScriptInAnyLang
 -> ExceptT SophieAddressCmdError IO ScriptInAnyLang)
-> ExceptT (FileError ScriptDecodeError) IO ScriptInAnyLang
-> ExceptT SophieAddressCmdError IO ScriptInAnyLang
forall a b. (a -> b) -> a -> b
$
            String -> ExceptT (FileError ScriptDecodeError) IO ScriptInAnyLang
readFileScriptInAnyLang String
fp

        let stakeCred :: StakeCredential
stakeCred = ScriptHash -> StakeCredential
StakeCredentialByScript (Script lang -> ScriptHash
forall lang. Script lang -> ScriptHash
hashScript Script lang
script)
        StakeAddressReference
-> ExceptT SophieAddressCmdError IO StakeAddressReference
forall (m :: * -> *) a. Monad m => a -> m a
return (StakeCredential -> StakeAddressReference
StakeAddressByValue StakeCredential
stakeCred)

buildSophieAddress
  :: VerificationKey PaymentKey
  -> Maybe StakeVerifier
  -> NetworkId
  -> ExceptT SophieAddressCmdError IO (Address SophieAddr)
buildSophieAddress :: VerificationKey PaymentKey
-> Maybe StakeVerifier
-> NetworkId
-> ExceptT SophieAddressCmdError IO (Address SophieAddr)
buildSophieAddress VerificationKey PaymentKey
vkey Maybe StakeVerifier
mbStakeVerifier NetworkId
nw =
  NetworkId
-> PaymentCredential -> StakeAddressReference -> Address SophieAddr
makeSophieAddress NetworkId
nw (Hash PaymentKey -> PaymentCredential
PaymentCredentialByKey (VerificationKey PaymentKey -> Hash PaymentKey
forall keyrole.
Key keyrole =>
VerificationKey keyrole -> Hash keyrole
verificationKeyHash VerificationKey PaymentKey
vkey)) (StakeAddressReference -> Address SophieAddr)
-> ExceptT SophieAddressCmdError IO StakeAddressReference
-> ExceptT SophieAddressCmdError IO (Address SophieAddr)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe StakeVerifier
-> ExceptT SophieAddressCmdError IO StakeAddressReference
makeStakeAddressRef Maybe StakeVerifier
mbStakeVerifier


--
-- Handling the variety of address key types
--

-- TODO: if we could make unions like this an instance of the Key class then
-- it would simplify some of the code above
data SomeAddressVerificationKey
  = AColeVerificationKey           (VerificationKey ColeKey)
  | APaymentVerificationKey         (VerificationKey PaymentKey)
  | APaymentExtendedVerificationKey (VerificationKey PaymentExtendedKey)
  | AGenesisUTxOVerificationKey     (VerificationKey GenesisUTxOKey)
  deriving (Int -> SomeAddressVerificationKey -> ShowS
[SomeAddressVerificationKey] -> ShowS
SomeAddressVerificationKey -> String
(Int -> SomeAddressVerificationKey -> ShowS)
-> (SomeAddressVerificationKey -> String)
-> ([SomeAddressVerificationKey] -> ShowS)
-> Show SomeAddressVerificationKey
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SomeAddressVerificationKey] -> ShowS
$cshowList :: [SomeAddressVerificationKey] -> ShowS
show :: SomeAddressVerificationKey -> String
$cshow :: SomeAddressVerificationKey -> String
showsPrec :: Int -> SomeAddressVerificationKey -> ShowS
$cshowsPrec :: Int -> SomeAddressVerificationKey -> ShowS
Show)

foldSomeAddressVerificationKey :: (forall keyrole. Key keyrole =>
                                   VerificationKey keyrole -> a)
                               -> SomeAddressVerificationKey -> a
foldSomeAddressVerificationKey :: (forall keyrole. Key keyrole => VerificationKey keyrole -> a)
-> SomeAddressVerificationKey -> a
foldSomeAddressVerificationKey forall keyrole. Key keyrole => VerificationKey keyrole -> a
f (AColeVerificationKey           VerificationKey ColeKey
vk) = VerificationKey ColeKey -> a
forall keyrole. Key keyrole => VerificationKey keyrole -> a
f VerificationKey ColeKey
vk
foldSomeAddressVerificationKey forall keyrole. Key keyrole => VerificationKey keyrole -> a
f (APaymentVerificationKey         VerificationKey PaymentKey
vk) = VerificationKey PaymentKey -> a
forall keyrole. Key keyrole => VerificationKey keyrole -> a
f VerificationKey PaymentKey
vk
foldSomeAddressVerificationKey forall keyrole. Key keyrole => VerificationKey keyrole -> a
f (APaymentExtendedVerificationKey VerificationKey PaymentExtendedKey
vk) = VerificationKey PaymentExtendedKey -> a
forall keyrole. Key keyrole => VerificationKey keyrole -> a
f VerificationKey PaymentExtendedKey
vk
foldSomeAddressVerificationKey forall keyrole. Key keyrole => VerificationKey keyrole -> a
f (AGenesisUTxOVerificationKey     VerificationKey GenesisUTxOKey
vk) = VerificationKey GenesisUTxOKey -> a
forall keyrole. Key keyrole => VerificationKey keyrole -> a
f VerificationKey GenesisUTxOKey
vk

readAddressVerificationKeyTextOrFile
  :: VerificationKeyTextOrFile
  -> ExceptT VerificationKeyTextOrFileError IO SomeAddressVerificationKey
readAddressVerificationKeyTextOrFile :: VerificationKeyTextOrFile
-> ExceptT
     VerificationKeyTextOrFileError IO SomeAddressVerificationKey
readAddressVerificationKeyTextOrFile VerificationKeyTextOrFile
vkTextOrFile =
    IO
  (Either VerificationKeyTextOrFileError SomeAddressVerificationKey)
-> ExceptT
     VerificationKeyTextOrFileError IO SomeAddressVerificationKey
forall (m :: * -> *) x a. m (Either x a) -> ExceptT x m a
newExceptT (IO
   (Either VerificationKeyTextOrFileError SomeAddressVerificationKey)
 -> ExceptT
      VerificationKeyTextOrFileError IO SomeAddressVerificationKey)
-> IO
     (Either VerificationKeyTextOrFileError SomeAddressVerificationKey)
-> ExceptT
     VerificationKeyTextOrFileError IO SomeAddressVerificationKey
forall a b. (a -> b) -> a -> b
$
      [FromSomeType SerialiseAsBech32 SomeAddressVerificationKey]
-> [FromSomeType HasTextEnvelope SomeAddressVerificationKey]
-> VerificationKeyTextOrFile
-> IO
     (Either VerificationKeyTextOrFileError SomeAddressVerificationKey)
forall b.
[FromSomeType SerialiseAsBech32 b]
-> [FromSomeType HasTextEnvelope b]
-> VerificationKeyTextOrFile
-> IO (Either VerificationKeyTextOrFileError b)
readVerificationKeyTextOrFileAnyOf [FromSomeType SerialiseAsBech32 SomeAddressVerificationKey]
bech32Types [FromSomeType HasTextEnvelope SomeAddressVerificationKey]
textEnvTypes VerificationKeyTextOrFile
vkTextOrFile
  where
    bech32Types :: [FromSomeType SerialiseAsBech32 SomeAddressVerificationKey]
bech32Types =
      [ AsType (VerificationKey PaymentKey)
-> (VerificationKey PaymentKey -> SomeAddressVerificationKey)
-> FromSomeType SerialiseAsBech32 SomeAddressVerificationKey
forall (c :: * -> Constraint) a b.
c a =>
AsType a -> (a -> b) -> FromSomeType c b
FromSomeType (AsType PaymentKey -> AsType (VerificationKey PaymentKey)
forall a. AsType a -> AsType (VerificationKey a)
AsVerificationKey AsType PaymentKey
AsPaymentKey)
                     VerificationKey PaymentKey -> SomeAddressVerificationKey
APaymentVerificationKey
      , AsType (VerificationKey PaymentExtendedKey)
-> (VerificationKey PaymentExtendedKey
    -> SomeAddressVerificationKey)
-> FromSomeType SerialiseAsBech32 SomeAddressVerificationKey
forall (c :: * -> Constraint) a b.
c a =>
AsType a -> (a -> b) -> FromSomeType c b
FromSomeType (AsType PaymentExtendedKey
-> AsType (VerificationKey PaymentExtendedKey)
forall a. AsType a -> AsType (VerificationKey a)
AsVerificationKey AsType PaymentExtendedKey
AsPaymentExtendedKey)
                     VerificationKey PaymentExtendedKey -> SomeAddressVerificationKey
APaymentExtendedVerificationKey
      ]

    textEnvTypes :: [FromSomeType HasTextEnvelope SomeAddressVerificationKey]
textEnvTypes =
      [ AsType (VerificationKey ColeKey)
-> (VerificationKey ColeKey -> SomeAddressVerificationKey)
-> FromSomeType HasTextEnvelope SomeAddressVerificationKey
forall (c :: * -> Constraint) a b.
c a =>
AsType a -> (a -> b) -> FromSomeType c b
FromSomeType (AsType ColeKey -> AsType (VerificationKey ColeKey)
forall a. AsType a -> AsType (VerificationKey a)
AsVerificationKey AsType ColeKey
AsColeKey)
                     VerificationKey ColeKey -> SomeAddressVerificationKey
AColeVerificationKey
      , AsType (VerificationKey PaymentKey)
-> (VerificationKey PaymentKey -> SomeAddressVerificationKey)
-> FromSomeType HasTextEnvelope SomeAddressVerificationKey
forall (c :: * -> Constraint) a b.
c a =>
AsType a -> (a -> b) -> FromSomeType c b
FromSomeType (AsType PaymentKey -> AsType (VerificationKey PaymentKey)
forall a. AsType a -> AsType (VerificationKey a)
AsVerificationKey AsType PaymentKey
AsPaymentKey)
                     VerificationKey PaymentKey -> SomeAddressVerificationKey
APaymentVerificationKey
      , AsType (VerificationKey PaymentExtendedKey)
-> (VerificationKey PaymentExtendedKey
    -> SomeAddressVerificationKey)
-> FromSomeType HasTextEnvelope SomeAddressVerificationKey
forall (c :: * -> Constraint) a b.
c a =>
AsType a -> (a -> b) -> FromSomeType c b
FromSomeType (AsType PaymentExtendedKey
-> AsType (VerificationKey PaymentExtendedKey)
forall a. AsType a -> AsType (VerificationKey a)
AsVerificationKey AsType PaymentExtendedKey
AsPaymentExtendedKey)
                     VerificationKey PaymentExtendedKey -> SomeAddressVerificationKey
APaymentExtendedVerificationKey
      , AsType (VerificationKey GenesisUTxOKey)
-> (VerificationKey GenesisUTxOKey -> SomeAddressVerificationKey)
-> FromSomeType HasTextEnvelope SomeAddressVerificationKey
forall (c :: * -> Constraint) a b.
c a =>
AsType a -> (a -> b) -> FromSomeType c b
FromSomeType (AsType GenesisUTxOKey -> AsType (VerificationKey GenesisUTxOKey)
forall a. AsType a -> AsType (VerificationKey a)
AsVerificationKey AsType GenesisUTxOKey
AsGenesisUTxOKey)
                     VerificationKey GenesisUTxOKey -> SomeAddressVerificationKey
AGenesisUTxOVerificationKey
      ]

--
-- Multisig addresses
--

runAddressBuildScript
  :: ScriptFile
  -> NetworkId
  -> Maybe OutputFile
  -> ExceptT SophieAddressCmdError IO ()
runAddressBuildScript :: ScriptFile
-> NetworkId
-> Maybe OutputFile
-> ExceptT SophieAddressCmdError IO ()
runAddressBuildScript ScriptFile
scriptFile NetworkId
networkId Maybe OutputFile
mOutputFile = do
  IO () -> ExceptT SophieAddressCmdError IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ExceptT SophieAddressCmdError IO ())
-> IO () -> ExceptT SophieAddressCmdError IO ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
deprecationWarning String
"'address build'"
  PaymentVerifier
-> Maybe StakeVerifier
-> NetworkId
-> Maybe OutputFile
-> ExceptT SophieAddressCmdError IO ()
runAddressBuild (ScriptFile -> PaymentVerifier
PaymentVerifierScriptFile ScriptFile
scriptFile) Maybe StakeVerifier
forall a. Maybe a
Nothing NetworkId
networkId Maybe OutputFile
mOutputFile