cardano-addresses-4.0.0: lib/Options/Applicative/Style.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TypeApplications #-}
{-# OPTIONS_HADDOCK hide #-}
{-# OPTIONS_GHC -fno-warn-deprecations #-}
-- |
-- Copyright: 2020 Input Output (Hong Kong) Ltd., 2021-2022 Input Output Global Inc. (IOG), 2023-2025 Intersect
-- License: Apache-2.0
module Options.Applicative.Style
(
-- * Type
Style(..)
, Passphrase (..)
, PassphraseInfo (..)
, PassphraseInputMode (..)
, PassphraseInput (..)
, generateRootKey
-- * Applicative Parser
, styleArg
, passphraseInfoOpt
, passphraseInputModeOpt
, fileOpt
) where
import Prelude
import Cardano.Address.Derivation
( XPrv )
import Cardano.Mnemonic
( SomeMnemonic, someMnemonicToBytes )
import Control.Applicative
( (<|>) )
import Data.ByteArray
( ScrubbedBytes )
import Data.ByteString
( ByteString )
import Data.Char
( toLower )
import Data.List
( intercalate )
import Options.Applicative
( Parser
, argument
, completer
, eitherReader
, flag'
, help
, listCompleter
, long
, metavar
, option
)
import qualified Cardano.Address.Style.Byron as Byron
import qualified Cardano.Address.Style.Icarus as Icarus
import qualified Cardano.Address.Style.Shared as Shared
import qualified Cardano.Address.Style.Shelley as Shelley
import qualified Data.ByteArray as BA
--
-- Type
--
-- | Represent a style of wallet.
data Style
= Byron
| Icarus
| Shelley
| Shared
deriving (Eq, Show, Enum, Bounded)
-- | User chosen passphrase for the generation phase
--
-- @since 3.13.0
data Passphrase =
FromMnemonic SomeMnemonic | FromEncoded ByteString
deriving (Eq, Show)
data PassphraseInfo =
Mnemonic | Hex | Base64 | Utf8 | Octets
deriving (Eq, Show)
data PassphraseInputMode =
Sensitive | Silent | Explicit
deriving (Eq, Show)
data PassphraseInput =
Interactive | FromFile FilePath
deriving (Eq, Show)
toSndFactor :: Maybe Passphrase -> ScrubbedBytes
toSndFactor = \case
Nothing -> mempty
Just (FromMnemonic mnemonic) -> someMnemonicToBytes mnemonic
Just (FromEncoded bs) -> BA.convert bs
-- | Generate an extended root private key from a mnemonic sentence, in the
-- given style.
generateRootKey :: SomeMnemonic -> Maybe Passphrase -> Style -> IO XPrv
generateRootKey mw passwd = \case
Byron -> do
let rootK = Byron.genMasterKeyFromMnemonic mw
pure $ Byron.getKey rootK
Icarus -> do
let sndFactor = toSndFactor passwd
let rootK = Icarus.genMasterKeyFromMnemonic mw sndFactor
pure $ Icarus.getKey rootK
Shelley -> do
let sndFactor = toSndFactor passwd
let rootK = Shelley.genMasterKeyFromMnemonic mw sndFactor
pure $ Shelley.getKey rootK
Shared -> do
let sndFactor = toSndFactor passwd
let rootK = Shared.genMasterKeyFromMnemonic mw sndFactor
pure $ Shared.getKey rootK
--
-- Applicative Parser
--
-- | Parse a 'Style' from the command-line, as an argument.
styleArg :: Parser Style
styleArg = argument (eitherReader reader) $ mempty
<> metavar "STYLE"
<> help styles'
<> completer (listCompleter styles)
where
styles :: [String]
styles = show @Style <$> [minBound .. maxBound]
styles' = intercalate " | " styles
reader :: String -> Either String Style
reader str = case toLower <$> str of
"byron" -> Right Byron
"icarus" -> Right Icarus
"shelley" -> Right Shelley
"shared" -> Right Shared
_ -> Left $ "Unknown style; expecting one of " <> styles'
passphraseInfoReader :: String -> Either String PassphraseInfo
passphraseInfoReader s = maybe (Left err) Right (readPassphraseInfoMaybe s)
where
err = "Invalid passphrase input type. Must be one of the \
\allowed keywords: from-mnemonic, from-hex, from-base64, from-octets or from-utf8."
readPassphraseInfoMaybe str
| str == mempty = pure Utf8
| str == "from-mnemonic" = pure Mnemonic
| str == "from-hex" = pure Hex
| str == "from-base64" = pure Base64
| str == "from-utf8" = pure Utf8
| str == "from-octets" = pure Octets
| otherwise = Nothing
passphraseInfoOpt :: Parser PassphraseInfo
passphraseInfoOpt = option (eitherReader passphraseInfoReader) $ mempty
<> long "passphrase"
<> metavar "FORMAT"
<> help helpDoc
where
helpDoc =
"(from-mnemonic | from-hex | from-base64 | from-utf8 | from-octets) " ++
"User chosen passphrase to be read from stdin for the generation phase. " ++
"Valid for Icarus, Shelley and Shared styles. Accepting mnemonic " ++
"(9- or 12 words) or arbitrary passphrase encoded as base16, base64, plain utf8 " ++
"or raw bytes in the form of octet array."
-- | Parse an 'PassphraseInputMode' from the command-line, if there is proper flag then sensitive is set.
passphraseInputModeOpt :: Parser PassphraseInputMode
passphraseInputModeOpt = sensitive <|> silent <|> pure Explicit
where
sensitive = flag' Sensitive (long "sensitive" <> help ("Input is shown as * in interactive mode."))
silent = flag' Silent (long "silent" <> help ("Input is not shown in interactive mode."))
fileOpt :: Parser FilePath
fileOpt = option (eitherReader Right) $ mempty
<> long "from-file"
<> metavar "FILE"
<> help ("Passphrase from specified filepath.")