module Hydra.Utils where

import Crypto.Random (getRandomBytes)
import GHC.IO.Exception (userError)
import Hydra.Cardano.Api (File (..), FileError (FileIOError), Key (SigningKey), getVerificationKey, writeFileTextEnvelope)
import Hydra.Crypto (HydraKey, generateSigningKey)
import Hydra.Options (GenerateKeyPair (..))
import Hydra.Prelude
import System.Directory (doesFileExist)
import System.FilePath ((<.>))

genHydraKeys :: GenerateKeyPair -> IO (Either (FileError ()) ())
genHydraKeys :: GenerateKeyPair -> IO (Either (FileError ()) ())
genHydraKeys GenerateKeyPair{FilePath
outputFile :: FilePath
$sel:outputFile:GenerateKeyPair :: GenerateKeyPair -> FilePath
outputFile} = do
  Bool
fileExists <- FilePath -> IO Bool
doesFileExist FilePath
outputFile
  if Bool
fileExists
    then
      Either (FileError ()) () -> IO (Either (FileError ()) ())
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either (FileError ()) () -> IO (Either (FileError ()) ()))
-> Either (FileError ()) () -> IO (Either (FileError ()) ())
forall a b. (a -> b) -> a -> b
$
        FileError () -> Either (FileError ()) ()
forall a b. a -> Either a b
Left (FileError () -> Either (FileError ()) ())
-> FileError () -> Either (FileError ()) ()
forall a b. (a -> b) -> a -> b
$
          FilePath -> IOException -> FileError ()
forall e. FilePath -> IOException -> FileError e
FileIOError
            FilePath
outputFile
            (FilePath -> IOException
userError FilePath
"File already exists! Please remove it in order to generate new hydra keys.")
    else do
      SigningKey HydraKey
sk :: SigningKey HydraKey <- ByteString -> SigningKey HydraKey
generateSigningKey (ByteString -> SigningKey HydraKey)
-> IO ByteString -> IO (SigningKey HydraKey)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> IO ByteString
forall byteArray. ByteArray byteArray => Int -> IO byteArray
forall (m :: * -> *) byteArray.
(MonadRandom m, ByteArray byteArray) =>
Int -> m byteArray
getRandomBytes Int
16
      ExceptT (FileError ()) IO () -> IO (Either (FileError ()) ())
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT (ExceptT (FileError ()) IO () -> IO (Either (FileError ()) ()))
-> ExceptT (FileError ()) IO () -> IO (Either (FileError ()) ())
forall a b. (a -> b) -> a -> b
$ do
        IO (Either (FileError ()) ()) -> ExceptT (FileError ()) IO ()
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT (IO (Either (FileError ()) ()) -> ExceptT (FileError ()) IO ())
-> IO (Either (FileError ()) ()) -> ExceptT (FileError ()) IO ()
forall a b. (a -> b) -> a -> b
$ File Any 'Out
-> Maybe TextEnvelopeDescr
-> SigningKey HydraKey
-> IO (Either (FileError ()) ())
forall a content.
HasTextEnvelope a =>
File content 'Out
-> Maybe TextEnvelopeDescr -> a -> IO (Either (FileError ()) ())
writeFileTextEnvelope (FilePath -> File Any 'Out
forall content (direction :: FileDirection).
FilePath -> File content direction
File (FilePath
outputFile FilePath -> FilePath -> FilePath
<.> FilePath
"sk")) Maybe TextEnvelopeDescr
forall a. Maybe a
Nothing SigningKey HydraKey
sk
        IO (Either (FileError ()) ()) -> ExceptT (FileError ()) IO ()
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT (IO (Either (FileError ()) ()) -> ExceptT (FileError ()) IO ())
-> IO (Either (FileError ()) ()) -> ExceptT (FileError ()) IO ()
forall a b. (a -> b) -> a -> b
$ File Any 'Out
-> Maybe TextEnvelopeDescr
-> VerificationKey HydraKey
-> IO (Either (FileError ()) ())
forall a content.
HasTextEnvelope a =>
File content 'Out
-> Maybe TextEnvelopeDescr -> a -> IO (Either (FileError ()) ())
writeFileTextEnvelope (FilePath -> File Any 'Out
forall content (direction :: FileDirection).
FilePath -> File content direction
File (FilePath
outputFile FilePath -> FilePath -> FilePath
<.> FilePath
"vk")) Maybe TextEnvelopeDescr
forall a. Maybe a
Nothing (SigningKey HydraKey -> VerificationKey HydraKey
forall keyrole.
(Key keyrole, HasTypeProxy keyrole) =>
SigningKey keyrole -> VerificationKey keyrole
getVerificationKey SigningKey HydraKey
sk)