-- SPDX-FileCopyrightText: 2021 Oxhead Alpha
-- SPDX-License-Identifier: LicenseRef-MIT-OA

{-# OPTIONS_GHC -Wno-orphans #-}

-- | Utilities for parsing Morley types using @optparse-applicative@.

module Morley.CLI
  ( -- * Full parsers
    parserInfo
    -- * Options
  , contractFileOption
  , nowOption
  , levelOption
  , minBlockTimeOption
  , maxStepsOption
  , dbPathOption
  , txDataOption
  , keyHashOption
  , secretKeyOption
  , valueOption
  , mutezOption
  , addressOption
  , aliasOption
  , addressOrAliasOption
  , someAddressOrAliasOption
  , onelineOption
  , entrypointOption
  , mTextOption
  , payloadOption
  , timeOption
  ) where

import Data.Singletons (SingI)
import Fmt (pretty)
import Options.Applicative
  (footerDoc, fullDesc, header, help, helper, info, long, metavar, option, progDesc, strOption,
  switch)
import Options.Applicative qualified as Opt
import Options.Applicative.Help qualified as Pretty
import Options.Applicative.Help.Pretty (Doc)
import Text.Read (read)

import Morley.Michelson.Parser (MichelsonSource(..))
import Morley.Michelson.Parser qualified as P
import Morley.Michelson.Runtime (TxData(..), TxParam(..))
import Morley.Michelson.Runtime.GState (genesisAddress)
import Morley.Michelson.Text (MText)
import Morley.Michelson.Untyped (EpName)
import Morley.Michelson.Untyped qualified as U
import Morley.Tezos.Address
import Morley.Tezos.Address.Alias
import Morley.Tezos.Core (Mutez, Timestamp, parseTimestamp, timestampFromSeconds)
import Morley.Tezos.Crypto
import Morley.Util.CLI
import Morley.Util.Interpolate (itu)
import Morley.Util.Named

----------------------------------------------------------------------------
-- These options are mostly specifications of 'mkCLOptionParser'
-- for concrete types (with more specific names).
----------------------------------------------------------------------------

-- | Full parser for a client.
parserInfo
  :: "usage" :! Doc
  -> "description" :! String
  -> "header" :! String
  -> "parser" :! Opt.Parser s
  -> Opt.ParserInfo s
parserInfo :: forall s.
("usage" :! Doc)
-> ("description" :! String)
-> ("header" :! String)
-> ("parser" :! Parser s)
-> ParserInfo s
parserInfo
  (Name "usage" -> ("usage" :! Doc) -> Doc
forall (name :: Symbol) a. Name name -> (name :! a) -> a
arg IsLabel "usage" (Name "usage")
Name "usage"
#usage -> Doc
usage)
  (Name "description" -> ("description" :! String) -> String
forall (name :: Symbol) a. Name name -> (name :! a) -> a
arg IsLabel "description" (Name "description")
Name "description"
#description -> String
description)
  (Name "header" -> ("header" :! String) -> String
forall (name :: Symbol) a. Name name -> (name :! a) -> a
arg IsLabel "header" (Name "header")
Name "header"
#header -> String
clientHeader)
  (Name "parser" -> ("parser" :! Parser s) -> Parser s
forall (name :: Symbol) a. Name name -> (name :! a) -> a
arg IsLabel "parser" (Name "parser")
Name "parser"
#parser -> Parser s
parser) =
  Parser s -> InfoMod s -> ParserInfo s
forall a. Parser a -> InfoMod a -> ParserInfo a
info (Parser (s -> s)
forall a. Parser (a -> a)
helper Parser (s -> s) -> Parser s -> Parser s
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser s
parser) (InfoMod s -> ParserInfo s) -> InfoMod s -> ParserInfo s
forall a b. (a -> b) -> a -> b
$
  [InfoMod s] -> InfoMod s
forall a. Monoid a => [a] -> a
mconcat
    [ InfoMod s
forall a. InfoMod a
fullDesc
    , String -> InfoMod s
forall a. String -> InfoMod a
progDesc String
description
    , String -> InfoMod s
forall a. String -> InfoMod a
header String
clientHeader
    , Maybe Doc -> InfoMod s
forall a. Maybe Doc -> InfoMod a
footerDoc (Maybe Doc -> InfoMod s) -> Maybe Doc -> InfoMod s
forall a b. (a -> b) -> a -> b
$ Doc -> Maybe Doc
forall (f :: * -> *) a. Applicative f => a -> f a
pure Doc
usage
    ]

-- | Parser for path to a contract code.
contractFileOption :: Opt.Parser FilePath
contractFileOption :: Parser String
contractFileOption = Mod OptionFields String -> Parser String
forall s. IsString s => Mod OptionFields s -> Parser s
strOption (Mod OptionFields String -> Parser String)
-> Mod OptionFields String -> Parser String
forall a b. (a -> b) -> a -> b
$
  String -> Mod OptionFields String
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"contract" Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<>
  String -> Mod OptionFields String
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"FILEPATH" Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<>
  String -> Mod OptionFields String
forall (f :: * -> *) a. String -> Mod f a
help String
"Path to contract file"

-- | Parser for timelocked chest payload.
payloadOption :: Opt.Parser ByteString
payloadOption :: Parser ByteString
payloadOption = Mod OptionFields ByteString -> Parser ByteString
forall s. IsString s => Mod OptionFields s -> Parser s
strOption (Mod OptionFields ByteString -> Parser ByteString)
-> Mod OptionFields ByteString -> Parser ByteString
forall a b. (a -> b) -> a -> b
$
  String -> Mod OptionFields ByteString
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"payload" Mod OptionFields ByteString
-> Mod OptionFields ByteString -> Mod OptionFields ByteString
forall a. Semigroup a => a -> a -> a
<>
  String -> Mod OptionFields ByteString
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"PAYLOAD" Mod OptionFields ByteString
-> Mod OptionFields ByteString -> Mod OptionFields ByteString
forall a. Semigroup a => a -> a -> a
<>
  String -> Mod OptionFields ByteString
forall (f :: * -> *) a. String -> Mod f a
help String
"Chest payload"

-- | Parser for timelocked chest time.
timeOption :: Opt.Parser TLTime
timeOption :: Parser TLTime
timeOption = Maybe TLTime
-> ("name" :! String) -> ("help" :! String) -> Parser TLTime
forall a.
(Buildable a, HasCLReader a) =>
Maybe a -> ("name" :! String) -> ("help" :! String) -> Parser a
mkCLOptionParser
  Maybe TLTime
forall a. Maybe a
Nothing
  (IsLabel "name" (Name "name")
Name "name"
#name Name "name" -> String -> "name" :! String
forall (name :: Symbol) a. Name name -> a -> NamedF Identity a name
:! String
"time")
  (IsLabel "help" (Name "help")
Name "help"
#help Name "help" -> String -> "help" :! String
forall (name :: Symbol) a. Name name -> a -> NamedF Identity a name
:! String
"Time constant for timelocked chest")

-- | Parser for the time returned by @NOW@ instruction.
nowOption :: Opt.Parser (Maybe Timestamp)
nowOption :: Parser (Maybe Timestamp)
nowOption = Parser Timestamp -> Parser (Maybe Timestamp)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Parser Timestamp -> Parser (Maybe Timestamp))
-> Parser Timestamp -> Parser (Maybe Timestamp)
forall a b. (a -> b) -> a -> b
$ ReadM Timestamp -> Mod OptionFields Timestamp -> Parser Timestamp
forall a. ReadM a -> Mod OptionFields a -> Parser a
option ReadM Timestamp
parser (Mod OptionFields Timestamp -> Parser Timestamp)
-> Mod OptionFields Timestamp -> Parser Timestamp
forall a b. (a -> b) -> a -> b
$
  String -> Mod OptionFields Timestamp
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"now" Mod OptionFields Timestamp
-> Mod OptionFields Timestamp -> Mod OptionFields Timestamp
forall a. Semigroup a => a -> a -> a
<>
  String -> Mod OptionFields Timestamp
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"TIMESTAMP" Mod OptionFields Timestamp
-> Mod OptionFields Timestamp -> Mod OptionFields Timestamp
forall a. Semigroup a => a -> a -> a
<>
  String -> Mod OptionFields Timestamp
forall (f :: * -> *) a. String -> Mod f a
help String
"Timestamp that you want the runtime interpreter to use (default is now)"
  where
    parser :: ReadM Timestamp
parser =
      (Integer -> Timestamp
timestampFromSeconds (Integer -> Timestamp) -> ReadM Integer -> ReadM Timestamp
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadM Integer
forall a. Read a => ReadM a
Opt.auto) ReadM Timestamp -> ReadM Timestamp -> ReadM Timestamp
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
      (String -> Maybe Timestamp) -> ReadM Timestamp
forall a. (String -> Maybe a) -> ReadM a
Opt.maybeReader (Text -> Maybe Timestamp
parseTimestamp (Text -> Maybe Timestamp)
-> (String -> Text) -> String -> Maybe Timestamp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
forall a. ToText a => a -> Text
toText)


levelOption :: Opt.Parser (Maybe Natural)
levelOption :: Parser (Maybe Natural)
levelOption = Parser Natural -> Parser (Maybe Natural)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Parser Natural -> Parser (Maybe Natural))
-> Parser Natural -> Parser (Maybe Natural)
forall a b. (a -> b) -> a -> b
$ ReadM Natural -> Mod OptionFields Natural -> Parser Natural
forall a. ReadM a -> Mod OptionFields a -> Parser a
option ReadM Natural
parser (Mod OptionFields Natural -> Parser Natural)
-> Mod OptionFields Natural -> Parser Natural
forall a b. (a -> b) -> a -> b
$
  String -> Mod OptionFields Natural
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"level" Mod OptionFields Natural
-> Mod OptionFields Natural -> Mod OptionFields Natural
forall a. Semigroup a => a -> a -> a
<>
  String -> Mod OptionFields Natural
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"NATURAL" Mod OptionFields Natural
-> Mod OptionFields Natural -> Mod OptionFields Natural
forall a. Semigroup a => a -> a -> a
<>
  String -> Mod OptionFields Natural
forall (f :: * -> *) a. String -> Mod f a
help String
"Level of the block in transaction chain"
  where
    parser :: ReadM Natural
parser = (String -> Maybe Natural) -> ReadM Natural
forall a. (String -> Maybe a) -> ReadM a
Opt.maybeReader (Natural -> Maybe Natural
forall a. a -> Maybe a
Just (Natural -> Maybe Natural)
-> (String -> Natural) -> String -> Maybe Natural
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Natural
forall a. Read a => String -> a
read)

minBlockTimeOption :: Opt.Parser (Maybe Natural)
minBlockTimeOption :: Parser (Maybe Natural)
minBlockTimeOption = Parser Natural -> Parser (Maybe Natural)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Parser Natural -> Parser (Maybe Natural))
-> Parser Natural -> Parser (Maybe Natural)
forall a b. (a -> b) -> a -> b
$ ReadM Natural -> Mod OptionFields Natural -> Parser Natural
forall a. ReadM a -> Mod OptionFields a -> Parser a
option ReadM Natural
parser (Mod OptionFields Natural -> Parser Natural)
-> Mod OptionFields Natural -> Parser Natural
forall a b. (a -> b) -> a -> b
$
  String -> Mod OptionFields Natural
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"min-block-time" Mod OptionFields Natural
-> Mod OptionFields Natural -> Mod OptionFields Natural
forall a. Semigroup a => a -> a -> a
<>
  String -> Mod OptionFields Natural
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"NATURAL" Mod OptionFields Natural
-> Mod OptionFields Natural -> Mod OptionFields Natural
forall a. Semigroup a => a -> a -> a
<>
  String -> Mod OptionFields Natural
forall (f :: * -> *) a. String -> Mod f a
help String
"Minimum time between blocks"
  where
    parser :: ReadM Natural
parser = (String -> Maybe Natural) -> ReadM Natural
forall a. (String -> Maybe a) -> ReadM a
Opt.maybeReader (Natural -> Maybe Natural
forall a. a -> Maybe a
Just (Natural -> Maybe Natural)
-> (String -> Natural) -> String -> Maybe Natural
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Natural
forall a. Read a => String -> a
read)

-- | Parser for gas limit on contract execution.
maxStepsOption :: Opt.Parser Word64
maxStepsOption :: Parser Word64
maxStepsOption = Maybe Word64
-> ("name" :! String) -> ("help" :! String) -> Parser Word64
forall a.
(Buildable a, HasCLReader a) =>
Maybe a -> ("name" :! String) -> ("help" :! String) -> Parser a
mkCLOptionParser
  (Word64 -> Maybe Word64
forall a. a -> Maybe a
Just Word64
100500)
  (IsLabel "name" (Name "name")
Name "name"
#name Name "name" -> String -> "name" :! String
forall (name :: Symbol) a. Name name -> a -> NamedF Identity a name
:! String
"max-steps")
  (IsLabel "help" (Name "help")
Name "help"
#help Name "help" -> String -> "help" :! String
forall (name :: Symbol) a. Name name -> a -> NamedF Identity a name
:! String
"Max steps that you want the runtime interpreter to use")

-- | Parser for path to database with Morley state.
dbPathOption :: Opt.Parser FilePath
dbPathOption :: Parser String
dbPathOption = Mod OptionFields String -> Parser String
forall s. IsString s => Mod OptionFields s -> Parser s
Opt.strOption (Mod OptionFields String -> Parser String)
-> Mod OptionFields String -> Parser String
forall a b. (a -> b) -> a -> b
$
  String -> Mod OptionFields String
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"db" Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<>
  String -> Mod OptionFields String
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"FILEPATH" Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<>
  String -> Mod OptionFields String
forall (f :: * -> *) a. HasValue f => a -> Mod f a
Opt.value String
"db.json" Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<>
  String -> Mod OptionFields String
forall (f :: * -> *) a. String -> Mod f a
help String
"Path to DB with data which is used instead of real blockchain data" Mod OptionFields String
-> Mod OptionFields String -> Mod OptionFields String
forall a. Semigroup a => a -> a -> a
<>
  Mod OptionFields String
forall a (f :: * -> *). Show a => Mod f a
Opt.showDefault

aliasOption :: (SingI kind, L1AddressKind kind) => String -> Opt.Parser (Alias kind)
aliasOption :: forall (kind :: AddressKind).
(SingI kind, L1AddressKind kind) =>
String -> Parser (Alias kind)
aliasOption String
key = (Text -> Alias kind) -> Parser Text -> Parser (Alias kind)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> Alias kind
forall (kind :: AddressKind).
(SingI kind, L1AddressKind kind) =>
Text -> Alias kind
mkAlias (Parser Text -> Parser (Alias kind))
-> (Mod OptionFields Text -> Parser Text)
-> Mod OptionFields Text
-> Parser (Alias kind)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mod OptionFields Text -> Parser Text
forall s. IsString s => Mod OptionFields s -> Parser s
Opt.strOption (Mod OptionFields Text -> Parser (Alias kind))
-> Mod OptionFields Text -> Parser (Alias kind)
forall a b. (a -> b) -> a -> b
$
  String -> Mod OptionFields Text
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
key Mod OptionFields Text
-> Mod OptionFields Text -> Mod OptionFields Text
forall a. Semigroup a => a -> a -> a
<>
  String -> Mod OptionFields Text
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"ALIAS" Mod OptionFields Text
-> Mod OptionFields Text -> Mod OptionFields Text
forall a. Semigroup a => a -> a -> a
<>
  String -> Mod OptionFields Text
forall (f :: * -> *) a. String -> Mod f a
help String
"An alias to be associated with the originated contract's address, e.g: 'alice', 'bob'"

-- | Generic parser to read an option of 'AddressOrAlias' type.
addressOrAliasOption
  :: (SingI kind, L1AddressKind kind)
  => Maybe (AddressOrAlias kind)
  -> "name" :! String
  -> "help" :! String
  -> Opt.Parser (AddressOrAlias kind)
addressOrAliasOption :: forall (kind :: AddressKind).
(SingI kind, L1AddressKind kind) =>
Maybe (AddressOrAlias kind)
-> ("name" :! String)
-> ("help" :! String)
-> Parser (AddressOrAlias kind)
addressOrAliasOption = Maybe (AddressOrAlias kind)
-> ("name" :! String)
-> ("help" :! String)
-> Parser (AddressOrAlias kind)
forall a.
(Buildable a, HasCLReader a) =>
Maybe a -> ("name" :! String) -> ("help" :! String) -> Parser a
mkCLOptionParser

-- | Generic parser to read an option of 'SomeAddressOrAlias' type.
someAddressOrAliasOption
  :: Maybe SomeAddressOrAlias
  -> "name" :! String
  -> "help" :! String
  -> Opt.Parser SomeAddressOrAlias
someAddressOrAliasOption :: Maybe SomeAddressOrAlias
-> ("name" :! String)
-> ("help" :! String)
-> Parser SomeAddressOrAlias
someAddressOrAliasOption Maybe SomeAddressOrAlias
defValue (Name "name" -> ("name" :! String) -> String
forall (name :: Symbol) a. Name name -> (name :! a) -> a
arg IsLabel "name" (Name "name")
Name "name"
#name -> String
name) (Name "help" -> ("help" :! String) -> String
forall (name :: Symbol) a. Name name -> (name :! a) -> a
arg IsLabel "help" (Name "help")
Name "help"
#help -> String
hInfo) =
  ReadM SomeAddressOrAlias
-> Mod OptionFields SomeAddressOrAlias -> Parser SomeAddressOrAlias
forall a. ReadM a -> Mod OptionFields a -> Parser a
Opt.option (forall a. HasCLReader a => ReadM a
getReader @SomeAddressOrAlias) (Mod OptionFields SomeAddressOrAlias -> Parser SomeAddressOrAlias)
-> Mod OptionFields SomeAddressOrAlias -> Parser SomeAddressOrAlias
forall a b. (a -> b) -> a -> b
$ [Mod OptionFields SomeAddressOrAlias]
-> Mod OptionFields SomeAddressOrAlias
forall a. Monoid a => [a] -> a
mconcat
    [ String -> Mod OptionFields SomeAddressOrAlias
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
Opt.metavar (forall a. HasCLReader a => String
getMetavar @SomeAddressOrAlias)
    , String -> Mod OptionFields SomeAddressOrAlias
forall (f :: * -> *) a. HasName f => String -> Mod f a
Opt.long String
name
    -- Note: `Opt.help` ignores newlines, so we use `Opt.helpDoc` + `vsep` instead.
    -- We use `paragraph` to word-wrap the help text.
    , Maybe Doc -> Mod OptionFields SomeAddressOrAlias
forall (f :: * -> *) a. Maybe Doc -> Mod f a
Opt.helpDoc (Maybe Doc -> Mod OptionFields SomeAddressOrAlias)
-> Maybe Doc -> Mod OptionFields SomeAddressOrAlias
forall a b. (a -> b) -> a -> b
$ Doc -> Maybe Doc
forall a. a -> Maybe a
Just (Doc -> Maybe Doc) -> Doc -> Maybe Doc
forall a b. (a -> b) -> a -> b
$ [Doc] -> Doc
Pretty.vsep ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ (Chunk Doc -> Doc
forall a. Monoid a => Chunk a -> a
Pretty.extractChunk (Chunk Doc -> Doc) -> (String -> Chunk Doc) -> String -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Chunk Doc
Pretty.paragraph) (String -> Doc) -> [String] -> [Doc]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
      [ String
hInfo
      , [itu|
        When using an alias that is assigned to both a contract and an implicit account,
        use the prefix '#{contractPrefix}:' or '#{implicitPrefix}:' to disambiguate.
        |]
      ]
    , (SomeAddressOrAlias -> String)
-> Maybe SomeAddressOrAlias -> Mod OptionFields SomeAddressOrAlias
forall (f :: * -> *) a.
HasValue f =>
(a -> String) -> Maybe a -> Mod f a
maybeAddDefault SomeAddressOrAlias -> String
forall a b. (Buildable a, FromBuilder b) => a -> b
pretty Maybe SomeAddressOrAlias
defValue
    ]

-- | Parser for transaction parameters.
txDataOption :: Opt.Parser TxData
txDataOption :: Parser TxData
txDataOption =
  ImplicitAddress -> Value -> Mutez -> EpName -> TxData
mkTxData
    (ImplicitAddress -> Value -> Mutez -> EpName -> TxData)
-> Parser ImplicitAddress
-> Parser (Value -> Mutez -> EpName -> TxData)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe ImplicitAddress
-> ("name" :! String)
-> ("help" :! String)
-> Parser ImplicitAddress
forall (kind :: AddressKind).
SingI kind =>
Maybe (KindedAddress kind)
-> ("name" :! String)
-> ("help" :! String)
-> Parser (KindedAddress kind)
addressOption (ImplicitAddress -> Maybe ImplicitAddress
forall a. a -> Maybe a
Just ImplicitAddress
genesisAddress)
      (IsLabel "name" (Name "name")
Name "name"
#name Name "name" -> String -> "name" :! String
forall (name :: Symbol) a. Name name -> a -> NamedF Identity a name
:! String
"sender") (IsLabel "help" (Name "help")
Name "help"
#help Name "help" -> String -> "help" :! String
forall (name :: Symbol) a. Name name -> a -> NamedF Identity a name
:! String
"Sender address")
    Parser (Value -> Mutez -> EpName -> TxData)
-> Parser Value -> Parser (Mutez -> EpName -> TxData)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe Value
-> ("name" :! String) -> ("help" :! String) -> Parser Value
valueOption Maybe Value
forall a. Maybe a
Nothing
      (IsLabel "name" (Name "name")
Name "name"
#name Name "name" -> String -> "name" :! String
forall (name :: Symbol) a. Name name -> a -> NamedF Identity a name
:! String
"parameter") (IsLabel "help" (Name "help")
Name "help"
#help Name "help" -> String -> "help" :! String
forall (name :: Symbol) a. Name name -> a -> NamedF Identity a name
:! String
"Parameter of passed contract")
    Parser (Mutez -> EpName -> TxData)
-> Parser Mutez -> Parser (EpName -> TxData)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe Mutez
-> ("name" :! String) -> ("help" :! String) -> Parser Mutez
mutezOption (Mutez -> Maybe Mutez
forall a. a -> Maybe a
Just Mutez
forall a. Bounded a => a
minBound)
      (IsLabel "name" (Name "name")
Name "name"
#name Name "name" -> String -> "name" :! String
forall (name :: Symbol) a. Name name -> a -> NamedF Identity a name
:! String
"amount") (IsLabel "help" (Name "help")
Name "help"
#help Name "help" -> String -> "help" :! String
forall (name :: Symbol) a. Name name -> a -> NamedF Identity a name
:! String
"Amount sent by a transaction")
    Parser (EpName -> TxData) -> Parser EpName -> Parser TxData
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ("name" :! String) -> ("help" :! String) -> Parser EpName
entrypointOption (IsLabel "name" (Name "name")
Name "name"
#name Name "name" -> String -> "name" :! String
forall (name :: Symbol) a. Name name -> a -> NamedF Identity a name
:! String
"entrypoint") (IsLabel "help" (Name "help")
Name "help"
#help Name "help" -> String -> "help" :! String
forall (name :: Symbol) a. Name name -> a -> NamedF Identity a name
:! String
"Entrypoint to call")
  where
    mkTxData :: ImplicitAddress -> U.Value -> Mutez -> EpName -> TxData
    mkTxData :: ImplicitAddress -> Value -> Mutez -> EpName -> TxData
mkTxData ImplicitAddress
addr Value
param Mutez
amount EpName
epName =
      TxData :: L1Address -> TxParam -> EpName -> Mutez -> TxData
TxData
        { tdSenderAddress :: L1Address
tdSenderAddress = ImplicitAddress -> L1Address
forall {k} (c :: k -> Constraint) (f :: k -> *) (a :: k).
c a =>
f a -> Constrained c f
Constrained ImplicitAddress
addr
        , tdParameter :: TxParam
tdParameter = Value -> TxParam
TxUntypedParam Value
param
        , tdEntrypoint :: EpName
tdEntrypoint = EpName
epName
        , tdAmount :: Mutez
tdAmount = Mutez
amount
        }

-- | Generic parser to read an option of t'KeyHash' type.
keyHashOption ::
  Maybe KeyHash -> "name" :! String -> "help" :! String -> Opt.Parser KeyHash
keyHashOption :: Maybe KeyHash
-> ("name" :! String) -> ("help" :! String) -> Parser KeyHash
keyHashOption = Maybe KeyHash
-> ("name" :! String) -> ("help" :! String) -> Parser KeyHash
forall a.
(Buildable a, HasCLReader a) =>
Maybe a -> ("name" :! String) -> ("help" :! String) -> Parser a
mkCLOptionParser

-- | Generic parser to read an option of 'SecretKey' type.
secretKeyOption ::
  Maybe SecretKey -> "name" :! String -> "help" :! String -> Opt.Parser SecretKey
secretKeyOption :: Maybe SecretKey
-> ("name" :! String) -> ("help" :! String) -> Parser SecretKey
secretKeyOption = Maybe SecretKey
-> ("name" :! String) -> ("help" :! String) -> Parser SecretKey
forall a.
(Buildable a, HasCLReader a) =>
Maybe a -> ("name" :! String) -> ("help" :! String) -> Parser a
mkCLOptionParser

-- | Generic parser to read an option of 'U.Value' type.
valueOption ::
  Maybe U.Value -> "name" :! String -> "help" :! String -> Opt.Parser U.Value
valueOption :: Maybe Value
-> ("name" :! String) -> ("help" :! String) -> Parser Value
valueOption = Maybe Value
-> ("name" :! String) -> ("help" :! String) -> Parser Value
forall a.
(Buildable a, HasCLReader a) =>
Maybe a -> ("name" :! String) -> ("help" :! String) -> Parser a
mkCLOptionParser

-- | Generic parser to read an option of 'Mutez' type.
mutezOption ::
  Maybe Mutez -> "name" :! String -> "help" :! String -> Opt.Parser Mutez
mutezOption :: Maybe Mutez
-> ("name" :! String) -> ("help" :! String) -> Parser Mutez
mutezOption = Maybe Mutez
-> ("name" :! String) -> ("help" :! String) -> Parser Mutez
forall a.
(Buildable a, HasCLReader a) =>
Maybe a -> ("name" :! String) -> ("help" :! String) -> Parser a
mkCLOptionParser

-- | Generic parser to read an option of 'KindedAddress' type.
addressOption :: SingI kind =>
  Maybe (KindedAddress kind) -> "name" :! String -> "help" :! String -> Opt.Parser (KindedAddress kind)
addressOption :: forall (kind :: AddressKind).
SingI kind =>
Maybe (KindedAddress kind)
-> ("name" :! String)
-> ("help" :! String)
-> Parser (KindedAddress kind)
addressOption = Maybe (KindedAddress kind)
-> ("name" :! String)
-> ("help" :! String)
-> Parser (KindedAddress kind)
forall a.
(Buildable a, HasCLReader a) =>
Maybe a -> ("name" :! String) -> ("help" :! String) -> Parser a
mkCLOptionParser

-- | @--oneline@ flag.
onelineOption :: Opt.Parser Bool
onelineOption :: Parser Bool
onelineOption = Mod FlagFields Bool -> Parser Bool
switch (
  String -> Mod FlagFields Bool
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"oneline" Mod FlagFields Bool -> Mod FlagFields Bool -> Mod FlagFields Bool
forall a. Semigroup a => a -> a -> a
<>
  String -> Mod FlagFields Bool
forall (f :: * -> *) a. String -> Mod f a
help String
"Force single line output")

-- | Generic parser to read an option of 'EpName' type.
entrypointOption :: "name" :! String -> "help" :! String -> Opt.Parser EpName
entrypointOption :: ("name" :! String) -> ("help" :! String) -> Parser EpName
entrypointOption = Maybe EpName
-> ("name" :! String) -> ("help" :! String) -> Parser EpName
forall a.
(Buildable a, HasCLReader a) =>
Maybe a -> ("name" :! String) -> ("help" :! String) -> Parser a
mkCLOptionParser (EpName -> Maybe EpName
forall a. a -> Maybe a
Just EpName
U.DefEpName)

-- | Generic parser to read an option of 'MText' type.
mTextOption ::
  Maybe MText -> "name" :! String -> "help" :! String -> Opt.Parser MText
mTextOption :: Maybe MText
-> ("name" :! String) -> ("help" :! String) -> Parser MText
mTextOption = Maybe MText
-> ("name" :! String) -> ("help" :! String) -> Parser MText
forall a.
(Buildable a, HasCLReader a) =>
Maybe a -> ("name" :! String) -> ("help" :! String) -> Parser a
mkCLOptionParser

----------------------------------------------------------------------------
-- 'HasCLReader' orphan instances (better to avoid)
----------------------------------------------------------------------------

-- This instance uses parser which is not in the place where 'U.Value'
-- is defined, hence it is orphan.
instance HasCLReader U.Value where
  getReader :: ReadM Value
getReader = (String -> Either String Value) -> ReadM Value
forall a. (String -> Either String a) -> ReadM a
eitherReader String -> Either String Value
parseValue
    where
      parseValue :: String -> Either String U.Value
      parseValue :: String -> Either String Value
parseValue =
        (ParserException -> String)
-> Either ParserException Value -> Either String Value
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first (String -> String -> String
forall a. Monoid a => a -> a -> a
mappend String
"Failed to parse value: " (String -> String)
-> (ParserException -> String) -> ParserException -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ParserException -> String
forall e. Exception e => e -> String
displayException) (Either ParserException Value -> Either String Value)
-> (String -> Either ParserException Value)
-> String
-> Either String Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
        MichelsonSource -> Text -> Either ParserException Value
P.parseExpandValue MichelsonSource
MSCli (Text -> Either ParserException Value)
-> (String -> Text) -> String -> Either ParserException Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
        String -> Text
forall a. ToText a => a -> Text
toText
  getMetavar :: String
getMetavar = String
"MICHELSON VALUE"