packages feed

cardano-addresses-4.0.0: lib/Command/Key/Inspect.hs

{-# LANGUAGE FlexibleContexts #-}
{-# 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.Inspect
    ( Cmd (..)
    , mod
    , run
    ) where

import Prelude hiding
    ( mod )

import Cardano.Address.Derivation
    ( XPrv, XPub, xprvChainCode, xprvPrivateKey, xpubChainCode, xpubPublicKey )
import Codec.Binary.Bech32
    ( HumanReadablePart )
import Codec.Binary.Encoding
    ( AbstractEncoding (..), encode )
import Data.Aeson
    ( (.=) )
import Data.ByteString
    ( ByteString )
import Data.Text
    ( Text )
import Options.Applicative
    ( CommandFields, Mod, command, footerDoc, helper, info, progDesc )
import Options.Applicative.Help.Pretty
    ( pretty )
import System.IO
    ( stdin, stdout )
import System.IO.Extra
    ( hGetXP__ )

import qualified Cardano.Codec.Bech32.Prefixes as CIP5
import qualified Data.Aeson as Json
import qualified Data.Aeson.Encode.Pretty as Json
import qualified Data.ByteString.Lazy.Char8 as BL8
import qualified Data.Text.Encoding as T


data Cmd = Inspect
    deriving (Show)

mod :: (Cmd -> parent) -> Mod CommandFields parent
mod liftCmd = command "inspect" $
    info (helper <*> fmap liftCmd parser) $ mempty
        <> progDesc "Show information about a key"
        <> footerDoc (Just $ pretty $ mconcat
            [ "The parent key is read from stdin." :: Text
            ])
  where
    parser = pure Inspect

run :: Cmd -> IO ()
run Inspect = do
    either inspectXPub inspectXPrv =<< hGetXP__ stdin allowedPrefixes
  where
    allowedPrefixes :: [HumanReadablePart]
    allowedPrefixes =
        [ CIP5.root_xvk
        , CIP5.root_xsk
        , CIP5.acct_xvk
        , CIP5.acct_xsk
        , CIP5.addr_xvk
        , CIP5.addr_xsk
        , CIP5.stake_xvk
        , CIP5.stake_xsk
        , CIP5.policy_xvk
        , CIP5.policy_xsk
        , CIP5.root_shared_xvk
        , CIP5.root_shared_xsk
        , CIP5.acct_shared_xvk
        , CIP5.acct_shared_xsk
        , CIP5.addr_shared_xvk
        , CIP5.addr_shared_xsk
        , CIP5.stake_shared_xvk
        , CIP5.stake_shared_xsk
        , CIP5.drep_xvk
        , CIP5.drep_xsk
        , CIP5.cc_cold_xvk
        , CIP5.cc_cold_xsk
        , CIP5.cc_hot_xvk
        , CIP5.cc_hot_xsk
        ]

    base16 :: ByteString -> Text
    base16 = T.decodeUtf8 . encode EBase16

    inspectXPub :: (HumanReadablePart, XPub) -> IO ()
    inspectXPub (_, xpub) = do
        BL8.hPutStrLn stdout $ Json.encodePretty $ Json.object
            [ "key_type" .= Json.String "public"
            , "extended_key" .= Json.String (base16 pub)
            , "chain_code" .= Json.String (base16 cc)
            ]
      where
        pub = xpubPublicKey xpub
        cc  = xpubChainCode xpub

    inspectXPrv :: (HumanReadablePart, XPrv) -> IO ()
    inspectXPrv (_, xprv) =
        BL8.hPutStrLn stdout $ Json.encodePretty $ Json.object
            [ "key_type" .= Json.String "private"
            , "extended_key" .= Json.String (base16 prv)
            , "chain_code" .= Json.String (base16 cc)
            ]
      where
        prv = xprvPrivateKey xprv
        cc  = xprvChainCode  xprv