-- SPDX-FileCopyrightText: 2023 Oxhead Alpha -- SPDX-License-Identifier: LicenseRef-MIT-OA -- | Various error types. module Morley.Client.TezosClient.Types.Errors ( TezosClientError (..) , ResolveError(..) ) where import Fmt (Buildable(..), pretty, (+|), (|+)) import Data.Constraint ((\\)) import Data.Singletons (demote) import Data.Text qualified as T import Lorentz.Value import Morley.Client.RPC.Types import Morley.Tezos.Address import Morley.Tezos.Address.Alias import Morley.Tezos.Address.Kinds import Morley.Tezos.Crypto import Morley.Util.Constrained import Morley.Util.Interpolate (itu) -- | A data type for all /predicatable/ errors that can happen during -- @octez-client@ usage. data TezosClientError = UnexpectedClientFailure -- ^ @octez-client@ call unexpectedly failed (returned non-zero exit code). -- The error contains the error code, stdout and stderr contents. Int -- ^ Exit code Text -- ^ stdout Text -- ^ stderr -- These errors represent specific known scenarios. | AlreadyRevealed -- ^ Public key of the given address is already revealed. ImplicitAlias -- ^ Address alias that has already revealed its key | InvalidOperationHash -- ^ Can't wait for inclusion of operation with given hash because -- the hash is invalid. OperationHash | CounterIsAlreadyUsed -- ^ Error that indicates when given counter is already used for -- given contract. Text -- ^ Raw counter Text -- ^ Raw address | EConnreset -- ^ Network error with which @octez-client@ fails from time to time. -- Note: the errors below most likely indicate that something is wrong in our code. -- Maybe we made a wrong assumption about @octez-client@ or just didn't consider some case. -- Another possible reason that a broken @octez-client@ is used. | ConfigParseError String -- ^ A parse error occurred during config parsing. | TezosClientCryptoParseError Text CryptoParseError -- ^ @octez-client@ produced a cryptographic primitive that we can't parse. | TezosClientParseAddressError Text ParseAddressError -- ^ @octez-client@ produced an address that we can't parse. | TezosClientParseFeeError Text Text -- ^ @octez-client@ produced invalid output for parsing baker fee | TezosClientUnexpectedOutputFormat Text -- ^ @octez-client@ printed a string that doesn't match the format we expect. | CantRevealContract -- ^ Given alias is a contract and cannot be revealed. ImplicitAlias -- ^ Address alias of implicit account | ContractSender ContractAddress Text -- ^ Given contract is a source of a transfer or origination operation. | EmptyImplicitContract -- ^ Given alias is an empty implicit contract. ImplicitAlias -- ^ Address alias of implicit contract | TezosClientUnexpectedSignatureOutput Text -- ^ @octez-client sign bytes@ produced unexpected output format | TezosClientParseEncryptionTypeError Text Text -- ^ @octez-client@ produced invalid output for parsing secret key encryption type. | DuplicateAlias Text -- ^ Tried to save alias, but such alias already exists. | ResolveError ResolveError deriving stock instance Show TezosClientError instance Exception TezosClientError where displayException = pretty instance Buildable TezosClientError where build = \case UnexpectedClientFailure errCode output errOutput -> "`octez-client` unexpectedly failed with error code " +| errCode |+ ". Stdout:\n" +| output |+ "\nStderr:\n" +| errOutput |+ "" AlreadyRevealed alias -> "The address alias " <> build alias <> " is already revealed" InvalidOperationHash hash -> "Can't wait for inclusion of operation " <> build hash <> " because this hash is invalid." CounterIsAlreadyUsed counter addr -> "Counter " +| counter |+ " already used for " +| addr |+ "." EConnreset -> "`octez-client` call failed with 'Unix.ECONNRESET' error." ConfigParseError err -> "A parse error occurred during config parsing: " <> build err TezosClientCryptoParseError txt err -> "`octez-client` produced a cryptographic primitive that we can't parse: " +| txt |+ ".\n The error is: " +| err |+ "." TezosClientParseAddressError txt err -> "`octez-client` produced an address that we can't parse: " +| txt |+ ".\n The error is: " +| err |+ "." TezosClientParseFeeError txt err -> "`octez-client` produced invalid output for parsing baker fee: " +| txt |+ ".\n Parsing error is: " +| err |+ "" TezosClientUnexpectedOutputFormat txt -> "`octez-client` printed a string that doesn't match the format we expect:\n" <> build txt CantRevealContract alias -> "Contracts (" <> build alias <> ") cannot be revealed" ContractSender addr opName -> "Contract (" <> build addr <> ") cannot be source of " +| opName |+ "" EmptyImplicitContract alias -> "Empty implicit contract (" <> build alias <> ")" TezosClientUnexpectedSignatureOutput txt -> "`octez-client sign bytes` call returned a signature in format we don't expect:\n" <> build txt TezosClientParseEncryptionTypeError txt err -> "`octez-client` produced invalid output for parsing secret key encryption type: " +| txt |+ ".\n Parsing error is: " +| err |+ "" DuplicateAlias alias -> "Attempted to save alias '" +| alias |+ "', but it already exists" ResolveError err -> build err data ResolveError where REAliasNotFound :: Text -> ResolveError -- ^ Could not find an address with given alias. REWrongKind :: Alias expectedKind -> Address -> ResolveError -- ^ Expected an alias to be associated with an implicit address, but it was -- associated with a contract address, or vice-versa. REAddressNotFound :: KindedAddress kind -> ResolveError -- ^ Could not find an alias with given address. REAmbiguousAlias :: Text -> [L1Address] -> ResolveError -- ^ Expected an alias to be associated with either an implicit address or a -- contract address, but it was associated with both. deriving stock instance Show ResolveError instance Buildable ResolveError where build = \case REWrongKind (alias :: Alias expectedKind) (Constrained (addr :: KindedAddress actualKind)) -> [itu| Expected the alias '#{alias}' to be assigned to an address of kind '#{demotedExpectedKind}', but it's assigned to an address of kind '#{demotedActualKind}': #{addr}. |] where demotedExpectedKind = demote @expectedKind \\ aliasKindSanity alias :: AddressKind demotedActualKind = demote @actualKind \\ addressKindSanity addr :: AddressKind REAliasNotFound aliasText -> [itu|Could not find the alias '#{aliasText}'.|] REAddressNotFound addr -> [itu|Could not find an alias for the address '#{addr}'.|] REAmbiguousAlias aliasText addrs -> [itu| The alias '#{aliasText}' is assigned to: #{addrs'} Use '#{contractPrefix}:#{aliasText}' or '#{implicitPrefix}:#{aliasText}' to disambiguate. |] where addrs' = T.intercalate "\n" . toList $ addrs <&> foldConstrained \case ContractAddress contractAddr -> [itu|* a contract address: #{contractAddr}|] ImplicitAddress implicitAddr -> [itu|* an implicit address: #{implicitAddr}|]