packages feed

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

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}

{-# OPTIONS_HADDOCK hide #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}

-- |
-- Copyright: 2020 Input Output (Hong Kong) Ltd., 2021-2022 Input Output Global Inc. (IOG), 2023-2025 Intersect
-- License: Apache-2.0

module Command.Address.Inspect
    ( Cmd (..)
    , mod
    , run
    ) where

import Prelude hiding
    ( mod )

import Cardano.Address
    ( Address, unsafeMkAddress )
import Cardano.Address.Derivation
    ( XPub )
import Control.Applicative
    ( optional )
import Control.Exception
    ( displayException )
import Data.Text
    ( Text )
import Fmt
    ( format )
import Options.Applicative
    ( CommandFields, Mod, command, footerDoc, helper, info, progDesc )
import Options.Applicative.Derivation
    ( xpubOpt )
import Options.Applicative.Help.Pretty
    ( Doc, annotate, bold, indent, pretty, vsep )
import System.Exit
    ( die )
import System.IO
    ( stdin, stdout )
import System.IO.Extra
    ( hGetBytes, progName )

import qualified Cardano.Address.Style.Shelley as Shelley
import qualified Cardano.Codec.Bech32.Prefixes as CIP5
import qualified Data.Aeson.Encode.Pretty as Json
import qualified Data.ByteString.Lazy.Char8 as BL8

newtype Cmd = Inspect
    { rootPublicKey :: Maybe XPub
    } deriving (Show)

mod :: (Cmd -> parent) -> Mod CommandFields parent
mod liftCmd = command "inspect" $
    info (helper <*> fmap liftCmd parser) $ mempty
        <> progDesc "Show information about an address"
        <> footerDoc (Just $ vsep
            [ prettyText "The address is read from stdin."
            , prettyText ""
            , prettyText "Example:"
            , indent 2 $ annotate bold $ prettyText "$ cat addr.prv \\"
            , indent 4 $ annotate bold $ pretty $ "| "<>progName<>" key public --with-chain-code \\"
            , indent 4 $ annotate bold $ pretty $ "| "<>progName<>" address payment --network-tag testnet \\"
            , indent 4 $ annotate bold $ pretty $ "| "<>progName<>" address delegation $(cat stake.prv | "<>progName<>" key public --with-chain-code) \\"
            , indent 4 $ annotate bold $ pretty $ "| "<>progName<>" address inspect"
            , indent 2 $ prettyText "{"
            , indent 2 $ prettyText "    \"address_style\": \"Shelley\","
            , indent 2 $ prettyText "    \"stake_reference\": \"by value\","
            , indent 2 $ prettyText "    \"stake_key_hash\": \"6b542d6da35e6c95d95a33c6f66ec482d3f4caf3ad35e2ede09cf827\","
            , indent 2 $ prettyText "    \"spending_key_hash\": \"44bc4f524f49a78a9c8a45b882d8710cb9254b3da6a978d50dc9b870\","
            , indent 2 $ prettyText "    \"network_tag\": 0,"
            , indent 2 $ prettyText "    \"address_type\": 0"
            , indent 2 $ prettyText "}"
            ])
  where
    parser = Inspect
        <$> optional (xpubOpt [CIP5.root_xvk] "root" helpDoc)
    helpDoc =
        "A root public key. If specified, tries to decrypt the derivation path \
        \of Byron addresses."

    prettyText :: Text -> Doc
    prettyText = pretty

run :: Cmd -> IO ()
run Inspect{rootPublicKey} = do
    bytes <- hGetBytes stdin
    case inspect (unsafeMkAddress bytes) of
      Right json -> BL8.hPutStrLn stdout (Json.encodePretty json)
      Left  e    -> die $ format "Error: {}" (displayException e)
  where
    inspect :: Address -> Either Shelley.ErrInspectAddress Shelley.InspectAddress
    inspect = Shelley.eitherInspectAddress rootPublicKey