{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# OPTIONS_HADDOCK hide #-} -- | -- Copyright: 2020 Input Output (Hong Kong) Ltd., 2021-2022 Input Output Global Inc. (IOG), 2023-2025 Intersect -- License: Apache-2.0 module Command.Key.Public ( Cmd (..) , mod , run ) where import Prelude hiding ( mod ) import Cardano.Address.Derivation ( toXPub, xpubPublicKey, xpubToBytes ) import Codec.Binary.Encoding ( AbstractEncoding (..) ) import Data.Maybe ( fromJust ) import Data.Text ( Text ) import Options.Applicative ( CommandFields, Mod, command, footerDoc, helper, info, progDesc ) import Options.Applicative.Help.Pretty ( pretty ) import Options.Applicative.Public ( PublicType (..), publicOpt ) import System.IO ( stdin, stdout ) import System.IO.Extra ( hGetXPrv, hPutBytes ) import qualified Cardano.Codec.Bech32.Prefixes as CIP5 newtype Cmd = Public { chainCode :: PublicType } deriving (Show) mod :: (Cmd -> parent) -> Mod CommandFields parent mod liftCmd = command "public" $ info (helper <*> fmap liftCmd parser) $ mempty <> progDesc "Get the public counterpart of a private key" <> footerDoc (Just $ pretty $ mconcat [ "The private key is read from stdin." :: Text , "To get extended public key pass '--with-chain-code'." , "To get public key pass '--without-chain-code'." ]) where parser = Public <$> publicOpt run :: Cmd -> IO () run Public{chainCode} = do (hrp, xprv) <- hGetXPrv stdin allowedPrefixes let xpub = toXPub xprv let bytes = case chainCode of WithChainCode -> xpubToBytes xpub WithoutChainCode -> xpubPublicKey xpub hPutBytes stdout bytes (EBech32 $ prefixFor chainCode hrp) where prefixes = [ (CIP5.root_xsk, (CIP5.root_xvk, CIP5.root_vk) ) , (CIP5.acct_xsk, (CIP5.acct_xvk, CIP5.acct_vk) ) , (CIP5.addr_xsk, (CIP5.addr_xvk, CIP5.addr_vk) ) , (CIP5.stake_xsk, (CIP5.stake_xvk, CIP5.stake_vk) ) , (CIP5.root_shared_xsk, (CIP5.root_shared_xvk, CIP5.root_shared_vk) ) , (CIP5.acct_shared_xsk, (CIP5.acct_shared_xvk, CIP5.acct_shared_vk) ) , (CIP5.addr_shared_xsk, (CIP5.addr_shared_xvk, CIP5.addr_shared_vk) ) , (CIP5.stake_shared_xsk, (CIP5.stake_shared_xvk, CIP5.stake_shared_vk) ) , (CIP5.policy_xsk, (CIP5.policy_xvk, CIP5.policy_vk) ) , (CIP5.drep_xsk, (CIP5.drep_xvk, CIP5.drep_vk) ) , (CIP5.cc_cold_xsk, (CIP5.cc_cold_xvk, CIP5.cc_cold_vk) ) , (CIP5.cc_hot_xsk, (CIP5.cc_hot_xvk, CIP5.cc_hot_vk) ) ] allowedPrefixes = map fst prefixes getCC WithChainCode = fst getCC WithoutChainCode = snd prefixFor cc = getCC cc . fromJust . flip lookup prefixes