Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ADP-3306] Make additional API errors machine-readable. #4590

Merged
merged 17 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 32 additions & 14 deletions lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ import Cardano.Wallet.Api.Types
import Cardano.Wallet.Api.Types.Error
( ApiErrorBalanceTxUnderestimatedFee (..)
, ApiErrorInfo (..)
, ApiErrorMissingWitnessesInTransaction (..)
, ApiErrorNoSuchPool (..)
, ApiErrorNodeNotYetInRecentEra (..)
, ApiErrorNotEnoughMoney (..)
, ApiErrorNotEnoughMoneyShortfall (..)
Expand Down Expand Up @@ -640,21 +642,33 @@ instance IsServerError ErrSubmitTransaction where
toServerError = \case
ErrSubmitTransactionForeignWallet ->
apiError err403 ForeignTransaction $ mconcat
[ "The transaction to be submitted is foreign to the current wallet "
, "and cannot be sent. Submit a transaction that has either input "
, "or withdrawal belonging to the wallet."
[ "The transaction to be submitted is foreign to the current "
, "wallet and cannot be sent. Submit a transaction that has "
, "either an input or a withdrawal belonging to the wallet."
]
ErrSubmitTransactionPartiallySignedOrNoSignedTx expectedWitsNo foundWitsNo ->
apiError err403 MissingWitnessesInTransaction $ mconcat
[ "The transaction expects ", toText expectedWitsNo
, " witness(es) to be fully-signed but ", toText foundWitsNo, " was provided."
, " Submit fully-signed transaction."
ErrSubmitTransactionPartiallySignedOrNoSignedTx
expectedWitsNo foundWitsNo ->
flip (apiError err403) message $
MissingWitnessesInTransaction
ApiErrorMissingWitnessesInTransaction
{ expectedNumberOfKeyWits = fromIntegral expectedWitsNo
, detectedNumberOfKeyWits = fromIntegral foundWitsNo
}
where
message = mconcat
[ "The transaction expects "
, toText expectedWitsNo
, " witness(es) to be fully-signed but "
, toText foundWitsNo
, " was provided."
, " Please submit a fully-signed transaction."
]
ErrSubmitTransactionMultidelegationNotSupported ->
apiError err403 CreatedMultidelegationTransaction $ mconcat
[ "It looks like the transaction to be sent contains"
, "multiple delegations, which is not supported at this moment."
, "Please use at most one delegation action in a submitted transaction: join, quit or none."
[ "It looks like the transaction to be sent contains "
, "multiple delegations, which is not supported at this moment. "
, "Please use at most one delegation action in a submitted "
, "transaction: join, quit or none."
]

instance IsServerError ErrSubmitTx where
Expand Down Expand Up @@ -719,16 +733,20 @@ instance IsServerError ErrCannotJoin where
, " joining again would incur an unnecessary fee!"
]
ErrNoSuchPool pid ->
apiError err404 NoSuchPool $ mconcat
flip (apiError err404) message $
NoSuchPool ApiErrorNoSuchPool { poolId = pid }
where
message = mconcat
[ "I couldn't find any stake pool with the given id: "
, toText pid
]
ErrAlreadyDelegatingVoting pid ->
apiError err403 PoolAlreadyJoinedSameVote $ mconcat
[ "I couldn't join a stake pool with the given id: "
, toText pid
, " and vote. I have already joined this pool, also voted the same last time;"
, " joining/voting again would incur an unnecessary fee!"
, " and vote. I have already joined this pool, also voted the "
, "same last time; "
, "joining/voting again would incur an unnecessary fee!"
]

instance IsServerError ErrCannotVote where
Expand Down
24 changes: 24 additions & 0 deletions lib/api/src/Cardano/Wallet/Api/Types/Error.hs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ module Cardano.Wallet.Api.Types.Error
, ApiErrorNodeNotYetInRecentEra (..)
, ApiErrorNotEnoughMoney (..)
, ApiErrorNotEnoughMoneyShortfall (..)
, ApiErrorMissingWitnessesInTransaction (..)
, ApiErrorNoSuchPool (..)
)
where

Expand All @@ -49,6 +51,9 @@ import Cardano.Wallet.Api.Types.Amount
import Cardano.Wallet.Api.Types.WalletAssets
( ApiWalletAssets
)
import Cardano.Wallet.Primitive.Types.Pool
( PoolId
)
import Control.DeepSeq
( NFData (..)
)
Expand Down Expand Up @@ -145,11 +150,13 @@ data ApiErrorInfo
| MissingPolicyPublicKey
| MissingRewardAccount
| MissingWitnessesInTransaction
!ApiErrorMissingWitnessesInTransaction
| NetworkMisconfigured
| NetworkQueryFailed
| NetworkUnreachable
| NoRootKey
| NoSuchPool
!ApiErrorNoSuchPool
| NoSuchTransaction
| NoSuchWallet
| NoUtxosAvailable
Expand Down Expand Up @@ -273,6 +280,16 @@ data ApiErrorNodeNotYetInRecentEra = ApiErrorNodeNotYetInRecentEra
via DefaultRecord ApiErrorNodeNotYetInRecentEra
deriving anyclass NFData

data ApiErrorMissingWitnessesInTransaction =
ApiErrorMissingWitnessesInTransaction
{ expectedNumberOfKeyWits :: !Natural
, detectedNumberOfKeyWits :: !Natural
}
deriving (Data, Eq, Generic, Show, Typeable)
deriving (FromJSON, ToJSON)
via DefaultRecord ApiErrorMissingWitnessesInTransaction
deriving anyclass NFData

data ApiErrorNotEnoughMoney = ApiErrorNotEnoughMoney
{ shortfall :: !ApiErrorNotEnoughMoneyShortfall
}
Expand All @@ -288,3 +305,10 @@ data ApiErrorNotEnoughMoneyShortfall = ApiErrorNotEnoughMoneyShortfall
deriving (FromJSON, ToJSON) via
DefaultRecord ApiErrorNotEnoughMoneyShortfall
deriving anyclass NFData

data ApiErrorNoSuchPool = ApiErrorNoSuchPool
{ poolId :: !PoolId
}
deriving (Data, Eq, Generic, Show, Typeable)
deriving (FromJSON, ToJSON) via DefaultRecord ApiErrorNoSuchPool
deriving anyclass NFData
116 changes: 0 additions & 116 deletions lib/integration/framework/Test/Integration/Framework/TestData.hs
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,13 @@ module Test.Integration.Framework.TestData
-- * Error messages
, errMsg400WalletIdEncoding
, errMsg400StartTimeLaterThanEndTime
, errMsg403Fee
, errMsg403Collateral
, errMsg403NotAByronWallet
, errMsg403NotAnIcarusWallet
, errMsg403WrongPass
, errMsg403WrongMnemonic
, errMsg403AlreadyInLedger
, errMsg404NoSuchPool
, errMsg403PoolAlreadyJoined
, errMsg403NotDelegating
, errMsg403NonNullReward
, errMsg403NothingToMigrate
, errMsg404NoAsset
, errMsg404NoEndpoint
Expand All @@ -77,7 +73,6 @@ module Test.Integration.Framework.TestData
, errMsg500
, errMsg400NumberOfWords
, errMsgNotInDictionary
, errMsg400MinWithdrawalWrong
, errMsg403WithdrawalNotBeneficial
, errMsg403CouldntIdentifyAddrAsMine
, errMsg503PastHorizon
Expand All @@ -95,17 +90,6 @@ module Test.Integration.Framework.TestData
, errMsg403TemplateInvalidUnknownCosigner
, errMsg403TemplateInvalidDuplicateXPub
, errMsg403TemplateInvalidScript
, errMsg403InvalidConstructTx
, errMsg403ForeignTransaction
, errMsg403MissingWitsInTransaction
, errMsg403MultidelegationTransaction
, errMsg403MultiaccountTransaction
, errMsg403CreatedWrongPolicyScriptTemplateTx
, errMsg403CreatedWrongPolicyScriptTemplatePolicyId
, errMsg403AssetNameTooLong
, errMsg403MintOrBurnAssetQuantityOutOfBounds
, errMsg403InvalidValidityBounds
, errMsg403ValidityIntervalNotInsideScriptTimelock
) where

import Prelude
Expand Down Expand Up @@ -328,12 +312,6 @@ versionLine = "Running as " <> pack (showFullVersion version gitRevision)
--- Error messages
---

errMsg403InvalidConstructTx :: String
errMsg403InvalidConstructTx =
"It looks like I've created an empty transaction that does not have \
\any payments, withdrawals, delegations, metadata nor minting. \
\Include at least one of them."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🍾


errMsg409WalletExists :: String -> String
errMsg409WalletExists walId = "This operation would yield a wallet with the following\
\ id: " ++ walId ++ " However, I already know of a wallet with this id."
Expand All @@ -351,18 +329,6 @@ errMsg400StartTimeLaterThanEndTime startTime endTime = mconcat
, "'."
]

errMsg403Fee :: String
errMsg403Fee =
"I am unable to finalize the transaction, as there is not enough ada \
\available to pay for the fee and also pay for the minimum ada quantities \
\of all change outputs."

errMsg403Collateral :: String
errMsg403Collateral =
"I'm unable to create this transaction because the balance of pure ada \
\UTxOs in your wallet is insufficient to cover the minimum amount of \
\collateral required."

errMsg403NotAByronWallet :: String
errMsg403NotAByronWallet =
"I cannot derive new address for this wallet type.\
Expand Down Expand Up @@ -416,10 +382,6 @@ errMsg403WrongPass = "The given encryption passphrase doesn't match the one\
errMsg403WrongMnemonic :: String
errMsg403WrongMnemonic = "The given mnemonic doesn't match the one this wallet was created with"

errMsg400MinWithdrawalWrong :: String
errMsg400MinWithdrawalWrong = "The minimum withdrawal value must be at least \
\1 Lovelace."

errMsg403NothingToMigrate :: Text -> String
errMsg403NothingToMigrate _wid = mconcat
[ "I wasn't able to construct a migration plan. This could be "
Expand All @@ -441,10 +403,6 @@ errMsg403AlreadyInLedger :: Text -> String
errMsg403AlreadyInLedger tid = "The transaction with id: " ++ unpack tid ++
" cannot be forgotten as it is already in the ledger."

errMsg404NoSuchPool :: Text -> String
errMsg404NoSuchPool pid = "I couldn't find any stake pool with the given id: "
++ unpack pid

errMsg403PoolAlreadyJoined :: Text -> String
errMsg403PoolAlreadyJoined pid = "I couldn't join a stake pool with the given id: "
++ unpack pid ++ ". I have already joined this pool; joining again would "
Expand All @@ -455,10 +413,6 @@ errMsg403NotDelegating = "It seems that you're trying to retire from \
\delegation although you're not even delegating, nor won't be in an \
\immediate future."

errMsg403NonNullReward :: String
errMsg403NonNullReward = "It seems that you're trying to retire from delegation \
\although you've unspoiled rewards in your rewards account!"

errMsg404CannotFindTx :: Text -> String
errMsg404CannotFindTx tid = "I couldn't find a transaction with the given id: "
++ unpack tid
Expand Down Expand Up @@ -634,76 +588,6 @@ errMsg400ScriptNotUniformRoles :: String
errMsg400ScriptNotUniformRoles =
"All keys of a script must have the same role: either payment or delegation."

errMsg403ForeignTransaction :: String
errMsg403ForeignTransaction = mconcat
[ "The transaction to be submitted is foreign to the current wallet "
, "and cannot be sent. Submit a transaction that has either input "
, "or withdrawal belonging to the wallet."
]

errMsg403MissingWitsInTransaction :: Int -> Int -> String
errMsg403MissingWitsInTransaction expected got = mconcat
[ "The transaction expects ", show expected
, " witness(es) to be fully-signed but ", show got, " was provided."
, " Submit fully-signed transaction."
]

errMsg403MultidelegationTransaction :: String
errMsg403MultidelegationTransaction = mconcat
[ "It looks like I've created a transaction "
, "with multiple delegations, which is not supported at this moment. "
, "Please use at most one delegation action: join, quit or none."
]

errMsg403MultiaccountTransaction :: String
errMsg403MultiaccountTransaction = mconcat
[ "It looks like I've created a transaction "
, "with a delegation, which uses a stake key for the unsupported account. "
, "Please use delegation action engaging '0H' account."
]

errMsg403CreatedWrongPolicyScriptTemplateTx :: String
errMsg403CreatedWrongPolicyScriptTemplateTx = mconcat
[ "It looks like I've created a transaction with a minting/burning "
, "policy script that either does not pass validation, contains more "
, "than one cosigner, or has a cosigner that is different from cosigner#0."
]

errMsg403CreatedWrongPolicyScriptTemplatePolicyId :: String
errMsg403CreatedWrongPolicyScriptTemplatePolicyId = mconcat
[ "It looks like policy id is requested for a "
, "policy script that either does not pass validation, contains more "
, "than one cosigner, or has a cosigner that is different from cosigner#0."
]

errMsg403AssetNameTooLong :: String
errMsg403AssetNameTooLong = mconcat
[ "Attempted to create a transaction with an asset name that is "
, "too long. The maximum length is 32 bytes."
]

errMsg403MintOrBurnAssetQuantityOutOfBounds :: String
errMsg403MintOrBurnAssetQuantityOutOfBounds = mconcat
[ "Attempted to mint or burn an asset quantity that is out of "
, "bounds. The asset quantity must be greater than zero and must "
, "not exceed 9223372036854775807 (2^63 - 1)."
]

errMsg403InvalidValidityBounds :: String
errMsg403InvalidValidityBounds = unwords
[ "Attempted to create a transaction with invalid validity bounds."
, "Please make sure that the 'invalid_before' bound precedes the"
, "'invalid_hereafter' bound, and that you have not used negative"
, "time values."
]

errMsg403ValidityIntervalNotInsideScriptTimelock :: String
errMsg403ValidityIntervalNotInsideScriptTimelock = unwords
[ "Attempted to create a transaction with a validity interval"
, "that is not a subinterval of an associated script's timelock"
, "interval."
]

--------------------------------------------------------------------------------
-- Transaction metadata
--------------------------------------------------------------------------------
Expand Down
Loading
Loading