From 9b232a1bb3e251865b0a62017cb0b58402f771a2 Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Fri, 10 May 2024 14:30:47 +0200 Subject: [PATCH 01/17] Shelley TransactionNew part 1 --- .../Scenario/API/Shelley/TransactionsNew.hs | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs b/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs index fbb957dc3cb..5092f33bda4 100644 --- a/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs +++ b/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs @@ -328,13 +328,7 @@ import Test.Integration.Framework.DSL , (.>) ) import Test.Integration.Framework.TestData - ( errMsg403AssetNameTooLong - , errMsg403Collateral - , errMsg403CreatedWrongPolicyScriptTemplatePolicyId - , errMsg403CreatedWrongPolicyScriptTemplateTx - , errMsg403Fee - , errMsg403ForeignTransaction - , errMsg403InvalidConstructTx + ( errMsg403InvalidConstructTx , errMsg403InvalidValidityBounds , errMsg403MintOrBurnAssetQuantityOutOfBounds , errMsg403MissingWitsInTransaction @@ -922,8 +916,8 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do (Link.createUnsignedTransaction @'Shelley wa) Default payload verify rTx [ expectResponseCode HTTP.status403 - , expectErrorMessage errMsg403Fee ] + decodeErrorInfo rTx `shouldBe` CannotCoverFee it "TRANS_NEW_CREATE_04d - Not enough money" $ \ctx -> runResourceT $ do let minUTxOValue' = minUTxOValue (_mainEra ctx) @@ -2412,8 +2406,8 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do (Link.balanceTransaction @'Shelley wa) Default balancePayload verify rTx [ expectResponseCode HTTP.status403 - , expectErrorMessage errMsg403Fee ] + decodeErrorInfo rTx `shouldBe` CannotCoverFee -- This test is disabled because it contains an opaque fixture -- without a source code and it makes it impossible to update it @@ -2455,13 +2449,13 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do else ("4.280100", "[2.853400]") verify rTx' [ expectResponseCode HTTP.status403 - , expectErrorMessage errMsg403Collateral , expectErrorMessage $ "I need an ada amount of at least: " <> requiredAmt , expectErrorMessage $ "The largest combination of pure ada UTxOs I could find is: " <> largestFound ] + decodeErrorInfo rTx' `shouldBe` InsufficientCollateral -- This test is disabled because it contains an opaque fixture -- without a source code and it makes it impossible to update it @@ -2778,8 +2772,8 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do submittedTx <- submitTxWithWid ctx wb signedTx verify submittedTx [ expectResponseCode HTTP.status403 - , expectErrorMessage errMsg403ForeignTransaction ] + decodeErrorInfo submittedTx `shouldBe` ForeignTransaction describe "TRANS_NEW_SUBMIT_02 - Submitting on foreign Byron wallet is forbidden" $ do let scenarios = @@ -3797,8 +3791,8 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do (Link.createUnsignedTransaction @'Shelley wa) Default payload verify rTx [ expectResponseCode HTTP.status403 - , expectErrorMessage errMsg403CreatedWrongPolicyScriptTemplateTx ] + decodeErrorInfo rTx `shouldBe` CreatedWrongPolicyScriptTemplate it "TRANS_NEW_CREATE_10l - Minting when assetName too long" $ \ctx -> runResourceT $ do @@ -3824,8 +3818,8 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do (Link.createUnsignedTransaction @'Shelley wa) Default payload verify rTx [ expectResponseCode HTTP.status403 - , expectErrorMessage errMsg403AssetNameTooLong ] + decodeErrorInfo rTx `shouldBe` AssetNameTooLong it "TRANS_NEW_CREATE_10m1 - Minting amount too big" $ \ctx -> runResourceT $ do @@ -4229,8 +4223,8 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do (Link.createUnsignedTransaction @'Shelley wa) Default payload verify rTx [ expectResponseCode HTTP.status403 - , expectErrorMessage errMsg403CreatedWrongPolicyScriptTemplateTx ] + decodeErrorInfo rTx `shouldBe` CreatedWrongPolicyScriptTemplate describe "TRANS_NEW_CREATE_MINT_SCRIPTS - I can mint and burn with correct policy scripts" $ do let scenarios = @@ -4367,8 +4361,8 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do rGet <- request @ApiPolicyId ctx postPolicyId Default payload verify rGet [ expectResponseCode HTTP.status403 - , expectErrorMessage errMsg403CreatedWrongPolicyScriptTemplatePolicyId ] + decodeErrorInfo rGet `shouldBe` CreatedWrongPolicyScriptTemplate it "TRANS_NEW_CREATE_11 - Get policy id \ \" $ \ctx -> runResourceT $ do From 3e59e5013b5e7033921dea38a4448beb3a4f7891 Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Fri, 10 May 2024 17:43:33 +0200 Subject: [PATCH 02/17] Shelley TransactionNew part 2 --- .../Scenario/API/Shelley/TransactionsNew.hs | 36 +++++++------------ 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs b/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs index 5092f33bda4..2f267c522b5 100644 --- a/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs +++ b/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs @@ -328,15 +328,7 @@ import Test.Integration.Framework.DSL , (.>) ) import Test.Integration.Framework.TestData - ( errMsg403InvalidConstructTx - , errMsg403InvalidValidityBounds - , errMsg403MintOrBurnAssetQuantityOutOfBounds - , errMsg403MissingWitsInTransaction - , errMsg403MultiaccountTransaction - , errMsg403MultidelegationTransaction - , errMsg403NonNullReward - , errMsg403NotDelegating - , errMsg403ValidityIntervalNotInsideScriptTimelock + ( errMsg403MissingWitsInTransaction , errMsg404NoSuchPool , errMsg404NoWallet ) @@ -373,8 +365,8 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do (Link.createUnsignedTransaction @'Shelley wa) Default emptyPayload verify rTx [ expectResponseCode HTTP.status403 - , expectErrorMessage errMsg403InvalidConstructTx ] + decodeErrorInfo rTx `shouldBe` CreatedInvalidTransaction it "TRANS_NEW_CREATE_01b - Validity interval only is not allowed" $ \ctx -> runResourceT $ do @@ -397,8 +389,8 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do (Link.createUnsignedTransaction @'Shelley wa) Default validityInterval verify rTx [ expectResponseCode HTTP.status403 - , expectErrorMessage errMsg403InvalidConstructTx ] + decodeErrorInfo rTx `shouldBe` CreatedInvalidTransaction it "TRANS_NEW_CREATE_01c - No payload is bad request" $ \ctx -> runResourceT $ do wa <- fixtureWallet ctx @@ -3289,8 +3281,8 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do (Link.createUnsignedTransaction @'Shelley wa) Default delegations verify rTx [ expectResponseCode HTTP.status403 - , expectErrorMessage errMsg403MultidelegationTransaction ] + decodeErrorInfo rTx `shouldBe` CreatedMultidelegationTransaction it "TRANS_NEW_JOIN_01d - Multiaccount not supported" $ \ctx -> runResourceT $ do wa <- fixtureWallet ctx @@ -3307,8 +3299,8 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do (Link.createUnsignedTransaction @'Shelley wa) Default delegations verify rTx [ expectResponseCode HTTP.status403 - , expectErrorMessage errMsg403MultiaccountTransaction ] + decodeErrorInfo rTx `shouldBe` CreatedMultiaccountTransaction it "TRANS_NEW_JOIN_01e - Can re-join and withdraw at once" $ \ctx -> runResourceT $ do (src, _) <- rewardWallet ctx @@ -3593,8 +3585,8 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do (Link.createUnsignedTransaction @'Shelley wa) Default delegation verify rTx [ expectResponseCode HTTP.status403 - , expectErrorMessage errMsg403NotDelegating ] + decodeErrorInfo rTx `shouldBe` NotDelegatingTo it "TRANS_NEW_QUIT_02a - Cannot quit with rewards without explicit withdrawal" $ \ctx -> runResourceT $ do @@ -3606,12 +3598,12 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do } }] }|] - request @(ApiConstructTransaction n) ctx + rTx <- request @(ApiConstructTransaction n) ctx (Link.createUnsignedTransaction @'Shelley w) Default payload - >>= flip verify + verify rTx [ expectResponseCode HTTP.status403 - , expectErrorMessage errMsg403NonNullReward ] + decodeErrorInfo rTx `shouldBe` NonNullRewards it "TRANS_NEW_QUIT_02b - Can quit with rewards with explicit withdrawal" $ \ctx -> runResourceT $ do @@ -3843,9 +3835,8 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do (Link.createUnsignedTransaction @'Shelley wa) Default payload verify rTx [ expectResponseCode HTTP.status403 - , expectErrorMessage - errMsg403MintOrBurnAssetQuantityOutOfBounds ] + decodeErrorInfo rTx `shouldBe` MintOrBurnAssetQuantityOutOfBounds it "TRANS_NEW_CREATE_10m2 - Minting amount = 0" $ \ctx -> runResourceT $ do @@ -3869,8 +3860,8 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do (Link.createUnsignedTransaction @'Shelley wa) Default payload verify rTx [ expectResponseCode HTTP.status403 - , expectErrorMessage errMsg403MintOrBurnAssetQuantityOutOfBounds ] + decodeErrorInfo rTx `shouldBe` MintOrBurnAssetQuantityOutOfBounds it "TRANS_NEW_CREATE_10d - Minting assets without timelock" $ \ctx -> runResourceT $ do @@ -4010,9 +4001,8 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do (Link.createUnsignedTransaction @'Shelley wa) Default payload verify rTx [ expectResponseCode HTTP.status403 - , expectErrorMessage - errMsg403ValidityIntervalNotInsideScriptTimelock ] + decodeErrorInfo rTx `shouldBe` ValidityIntervalNotInsideScriptTimelock it "TRANS_NEW_CREATE_10f - Burning assets without timelock" $ \ctx -> runResourceT $ do @@ -4431,8 +4421,8 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do (Link.createUnsignedTransaction @'Shelley wa) Default payload verify rTx [ expectResponseCode HTTP.status403 - , expectErrorMessage errMsg403InvalidValidityBounds ] + decodeErrorInfo rTx `shouldBe` InvalidValidityBounds it "TRANS_NEW_VALIDITY_INTERVAL_02 - \ \Missing lower validity bound is acceptable" $ From adfd195fdb3a7e883f6b9ae98a91690dbe0316af Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Tue, 14 May 2024 13:16:20 +0200 Subject: [PATCH 03/17] refactor MissingWitsInTransaction --- .../Cardano/Wallet/Api/Http/Server/Error.hs | 9 +++++-- lib/api/src/Cardano/Wallet/Api/Types/Error.hs | 11 ++++++++ .../Test/Integration/Framework/TestData.hs | 8 ------ .../Scenario/API/Shared/Transactions.hs | 26 +++++++++++++++---- .../Scenario/API/Shelley/TransactionsNew.hs | 10 ++++--- .../test/unit/Cardano/Wallet/Api/TypesSpec.hs | 5 ++++ 6 files changed, 51 insertions(+), 18 deletions(-) diff --git a/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs b/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs index aa024803f74..4879e527e7c 100644 --- a/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs +++ b/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs @@ -108,6 +108,7 @@ import Cardano.Wallet.Api.Types import Cardano.Wallet.Api.Types.Error ( ApiErrorBalanceTxUnderestimatedFee (..) , ApiErrorInfo (..) + , ApiErrorMissingWitnessesInTransaction (..) , ApiErrorNodeNotYetInRecentEra (..) , ApiErrorNotEnoughMoney (..) , ApiErrorNotEnoughMoneyShortfall (..) @@ -645,11 +646,15 @@ instance IsServerError ErrSubmitTransaction where , "or withdrawal belonging to the wallet." ] ErrSubmitTransactionPartiallySignedOrNoSignedTx expectedWitsNo foundWitsNo -> - apiError err403 MissingWitnessesInTransaction $ mconcat + flip (apiError err403) (mconcat [ "The transaction expects ", toText expectedWitsNo , " witness(es) to be fully-signed but ", toText foundWitsNo, " was provided." , " Submit fully-signed transaction." - ] + ]) $ MissingWitnessesInTransaction + ApiErrorMissingWitnessesInTransaction + { expectedNumberOfKeyWits = fromIntegral expectedWitsNo + , detectedNumberOfKeyWits = fromIntegral foundWitsNo + } ErrSubmitTransactionMultidelegationNotSupported -> apiError err403 CreatedMultidelegationTransaction $ mconcat [ "It looks like the transaction to be sent contains" diff --git a/lib/api/src/Cardano/Wallet/Api/Types/Error.hs b/lib/api/src/Cardano/Wallet/Api/Types/Error.hs index b7bdfac3e90..f315cfa1094 100644 --- a/lib/api/src/Cardano/Wallet/Api/Types/Error.hs +++ b/lib/api/src/Cardano/Wallet/Api/Types/Error.hs @@ -29,6 +29,7 @@ module Cardano.Wallet.Api.Types.Error , ApiErrorNodeNotYetInRecentEra (..) , ApiErrorNotEnoughMoney (..) , ApiErrorNotEnoughMoneyShortfall (..) + , ApiErrorMissingWitnessesInTransaction (..) ) where @@ -145,6 +146,7 @@ data ApiErrorInfo | MissingPolicyPublicKey | MissingRewardAccount | MissingWitnessesInTransaction + !ApiErrorMissingWitnessesInTransaction | NetworkMisconfigured | NetworkQueryFailed | NetworkUnreachable @@ -273,6 +275,15 @@ 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 } diff --git a/lib/integration/framework/Test/Integration/Framework/TestData.hs b/lib/integration/framework/Test/Integration/Framework/TestData.hs index 1262123c4b7..334bd57d4bd 100644 --- a/lib/integration/framework/Test/Integration/Framework/TestData.hs +++ b/lib/integration/framework/Test/Integration/Framework/TestData.hs @@ -97,7 +97,6 @@ module Test.Integration.Framework.TestData , errMsg403TemplateInvalidScript , errMsg403InvalidConstructTx , errMsg403ForeignTransaction - , errMsg403MissingWitsInTransaction , errMsg403MultidelegationTransaction , errMsg403MultiaccountTransaction , errMsg403CreatedWrongPolicyScriptTemplateTx @@ -641,13 +640,6 @@ errMsg403ForeignTransaction = mconcat , "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 " diff --git a/lib/integration/scenarios/Test/Integration/Scenario/API/Shared/Transactions.hs b/lib/integration/scenarios/Test/Integration/Scenario/API/Shared/Transactions.hs index 3b030eb7d9d..8fbdc32b08f 100644 --- a/lib/integration/scenarios/Test/Integration/Scenario/API/Shared/Transactions.hs +++ b/lib/integration/scenarios/Test/Integration/Scenario/API/Shared/Transactions.hs @@ -63,6 +63,7 @@ import Cardano.Wallet.Api.Types.Amount ) import Cardano.Wallet.Api.Types.Error ( ApiErrorInfo (..) + , ApiErrorMissingWitnessesInTransaction (..) , ApiErrorTxOutputLovelaceInsufficient (ApiErrorTxOutputLovelaceInsufficient) ) import Cardano.Wallet.Api.Types.Transaction @@ -215,7 +216,6 @@ import Test.Integration.Framework.TestData , errMsg400StartTimeLaterThanEndTime , errMsg403Fee , errMsg403InvalidConstructTx - , errMsg403MissingWitsInTransaction , errMsg404CannotFindTx , errMsg404NoWallet ) @@ -1019,7 +1019,11 @@ spec = describe "SHARED_TRANSACTIONS" $ do submittedTx1 <- submitSharedTxWithWid ctx sharedWal1 signedTx1 verify submittedTx1 [ expectResponseCode HTTP.status403 - , expectErrorMessage (errMsg403MissingWitsInTransaction 2 1) + , expectErrorInfo $ flip shouldBe $ MissingWitnessesInTransaction $ + ApiErrorMissingWitnessesInTransaction + { expectedNumberOfKeyWits = 2 + , detectedNumberOfKeyWits = 1 + } ] -- adding the witness by the second participant make tx valid for @@ -1938,7 +1942,11 @@ spec = describe "SHARED_TRANSACTIONS" $ do submittedTx1 <- submitSharedTxWithWid ctx party1 signedTx1 verify submittedTx1 [ expectResponseCode HTTP.status403 - , expectErrorMessage (errMsg403MissingWitsInTransaction 3 2) + , expectErrorInfo $ flip shouldBe $ MissingWitnessesInTransaction $ + ApiErrorMissingWitnessesInTransaction + { expectedNumberOfKeyWits = 3 + , detectedNumberOfKeyWits = 2 + } ] let ApiSerialisedTransaction apiTx2 _ = signedTx1 @@ -3253,7 +3261,11 @@ spec = describe "SHARED_TRANSACTIONS" $ do submittedTx1 <- submitSharedTxWithWid ctx sharedWal1 signedTx1 verify submittedTx1 [ expectResponseCode HTTP.status403 - , expectErrorMessage (errMsg403MissingWitsInTransaction 2 1) + , expectErrorInfo $ flip shouldBe $ MissingWitnessesInTransaction $ + ApiErrorMissingWitnessesInTransaction + { expectedNumberOfKeyWits = 2 + , detectedNumberOfKeyWits = 1 + } ] --adding the witness by the same participant does not change the @@ -3276,7 +3288,11 @@ spec = describe "SHARED_TRANSACTIONS" $ do submittedTx2 <- submitSharedTxWithWid ctx sharedWal1 signedTx2 verify submittedTx2 [ expectResponseCode HTTP.status403 - , expectErrorMessage (errMsg403MissingWitsInTransaction 2 1) + , expectErrorInfo $ flip shouldBe $ MissingWitnessesInTransaction $ + ApiErrorMissingWitnessesInTransaction + { expectedNumberOfKeyWits = 2 + , detectedNumberOfKeyWits = 1 + } ] --adding the witness by the second participant make tx valid for diff --git a/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs b/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs index 2f267c522b5..f4d709a0600 100644 --- a/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs +++ b/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs @@ -112,6 +112,7 @@ import Cardano.Wallet.Api.Types.Certificate ) import Cardano.Wallet.Api.Types.Error ( ApiErrorInfo (..) + , ApiErrorMissingWitnessesInTransaction (..) , ApiErrorTxOutputLovelaceInsufficient (ApiErrorTxOutputLovelaceInsufficient) ) import Cardano.Wallet.Api.Types.Transaction @@ -328,8 +329,7 @@ import Test.Integration.Framework.DSL , (.>) ) import Test.Integration.Framework.TestData - ( errMsg403MissingWitsInTransaction - , errMsg404NoSuchPool + ( errMsg404NoSuchPool , errMsg404NoWallet ) import UnliftIO.Exception @@ -2659,7 +2659,11 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do submittedTx <- submitTxWithWid ctx w sealedTx verify submittedTx [ expectResponseCode HTTP.status403 - , expectErrorMessage (errMsg403MissingWitsInTransaction 1 0) + , expectErrorInfo $ flip shouldBe $ MissingWitnessesInTransaction $ + ApiErrorMissingWitnessesInTransaction + { expectedNumberOfKeyWits = 1 + , detectedNumberOfKeyWits = 0 + } ] it "TRANS_NEW_SIGN_03 - Sign withdrawals" $ \ctx -> runResourceT $ do diff --git a/lib/unit/test/unit/Cardano/Wallet/Api/TypesSpec.hs b/lib/unit/test/unit/Cardano/Wallet/Api/TypesSpec.hs index b78398a9a06..f3fadac480b 100644 --- a/lib/unit/test/unit/Cardano/Wallet/Api/TypesSpec.hs +++ b/lib/unit/test/unit/Cardano/Wallet/Api/TypesSpec.hs @@ -276,6 +276,7 @@ import Cardano.Wallet.Api.Types.Error , ApiErrorBalanceTxUnderestimatedFee (..) , ApiErrorInfo (..) , ApiErrorMessage (..) + , ApiErrorMissingWitnessesInTransaction (..) , ApiErrorNodeNotYetInRecentEra (..) , ApiErrorNotEnoughMoney (..) , ApiErrorNotEnoughMoneyShortfall (..) @@ -2458,6 +2459,10 @@ instance Arbitrary ApiErrorMessage where arbitrary = genericArbitrary shrink = genericShrink +instance Arbitrary ApiErrorMissingWitnessesInTransaction where + arbitrary = genericArbitrary + shrink = genericShrink + instance Arbitrary ApiErrorSharedWalletNoSuchCosigner where arbitrary = genericArbitrary shrink = genericShrink From 8b12005125fbc4c89cd23c0056d9b9a5740772e8 Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Tue, 14 May 2024 14:03:10 +0200 Subject: [PATCH 04/17] use MinWithdrawalWrong --- .../framework/Test/Integration/Framework/TestData.hs | 5 ----- .../Test/Integration/Scenario/API/Shared/Transactions.hs | 6 ++---- .../Test/Integration/Scenario/API/Shelley/Transactions.hs | 6 ++---- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/lib/integration/framework/Test/Integration/Framework/TestData.hs b/lib/integration/framework/Test/Integration/Framework/TestData.hs index 334bd57d4bd..2d0071b17b7 100644 --- a/lib/integration/framework/Test/Integration/Framework/TestData.hs +++ b/lib/integration/framework/Test/Integration/Framework/TestData.hs @@ -77,7 +77,6 @@ module Test.Integration.Framework.TestData , errMsg500 , errMsg400NumberOfWords , errMsgNotInDictionary - , errMsg400MinWithdrawalWrong , errMsg403WithdrawalNotBeneficial , errMsg403CouldntIdentifyAddrAsMine , errMsg503PastHorizon @@ -415,10 +414,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 " diff --git a/lib/integration/scenarios/Test/Integration/Scenario/API/Shared/Transactions.hs b/lib/integration/scenarios/Test/Integration/Scenario/API/Shared/Transactions.hs index 8fbdc32b08f..bb0ccb1f521 100644 --- a/lib/integration/scenarios/Test/Integration/Scenario/API/Shared/Transactions.hs +++ b/lib/integration/scenarios/Test/Integration/Scenario/API/Shared/Transactions.hs @@ -212,8 +212,7 @@ import Test.Integration.Framework.Request ( RequestException ) import Test.Integration.Framework.TestData - ( errMsg400MinWithdrawalWrong - , errMsg400StartTimeLaterThanEndTime + ( errMsg400StartTimeLaterThanEndTime , errMsg403Fee , errMsg403InvalidConstructTx , errMsg404CannotFindTx @@ -1580,8 +1579,7 @@ spec = describe "SHARED_TRANSACTIONS" $ do Nothing r <- request @([ApiTransaction n]) ctx link Default Empty expectResponseCode HTTP.status400 r - expectErrorMessage errMsg400MinWithdrawalWrong r - pure () + decodeErrorInfo r `shouldBe` MinWithdrawalWrong it "SHARED_TRANSACTIONS_LIST_03 - \ \Minimum withdrawal can be 1, shows empty when no withdrawals" $ diff --git a/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/Transactions.hs b/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/Transactions.hs index 53e81bb7e3b..5c27f20cc2b 100644 --- a/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/Transactions.hs +++ b/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/Transactions.hs @@ -214,8 +214,7 @@ import Test.Integration.Framework.Request ( RequestException ) import Test.Integration.Framework.TestData - ( errMsg400MinWithdrawalWrong - , errMsg400StartTimeLaterThanEndTime + ( errMsg400StartTimeLaterThanEndTime , errMsg400TxMetadataStringTooLong , errMsg403AlreadyInLedger , errMsg403Fee @@ -2167,8 +2166,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do Nothing r <- request @([ApiTransaction n]) ctx link Default Empty expectResponseCode HTTP.status400 r - expectErrorMessage errMsg400MinWithdrawalWrong r - pure () + decodeErrorInfo r `shouldBe` MinWithdrawalWrong it "TRANS_LIST_03 - \ From 55ba9b1677acf7531936d350d2bc373a5edee454 Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Tue, 14 May 2024 15:19:51 +0200 Subject: [PATCH 05/17] refactor NoSuchPool --- .../Cardano/Wallet/Api/Http/Server/Error.hs | 5 ++-- lib/api/src/Cardano/Wallet/Api/Types/Error.hs | 12 ++++++++ .../Test/Integration/Framework/TestData.hs | 5 ---- .../Scenario/API/Shelley/StakePools.hs | 29 ++++++++++++------- .../Scenario/API/Shelley/TransactionsNew.hs | 7 +++-- .../Cardano/Wallet/Primitive/Types/Pool.hs | 6 +++- .../test/unit/Cardano/Wallet/Api/TypesSpec.hs | 5 ++++ 7 files changed, 48 insertions(+), 21 deletions(-) diff --git a/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs b/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs index 4879e527e7c..f6ee35bf599 100644 --- a/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs +++ b/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs @@ -112,6 +112,7 @@ import Cardano.Wallet.Api.Types.Error , ApiErrorNodeNotYetInRecentEra (..) , ApiErrorNotEnoughMoney (..) , ApiErrorNotEnoughMoneyShortfall (..) + , ApiErrorNoSuchPool (..) , ApiErrorSharedWalletNoSuchCosigner (..) , ApiErrorTxOutputLovelaceInsufficient (..) ) @@ -724,10 +725,10 @@ instance IsServerError ErrCannotJoin where , " joining again would incur an unnecessary fee!" ] ErrNoSuchPool pid -> - apiError err404 NoSuchPool $ mconcat + flip (apiError err404) (mconcat [ "I couldn't find any stake pool with the given id: " , toText pid - ] + ]) $ NoSuchPool ApiErrorNoSuchPool { poolId = pid } ErrAlreadyDelegatingVoting pid -> apiError err403 PoolAlreadyJoinedSameVote $ mconcat [ "I couldn't join a stake pool with the given id: " diff --git a/lib/api/src/Cardano/Wallet/Api/Types/Error.hs b/lib/api/src/Cardano/Wallet/Api/Types/Error.hs index f315cfa1094..7820c74bd13 100644 --- a/lib/api/src/Cardano/Wallet/Api/Types/Error.hs +++ b/lib/api/src/Cardano/Wallet/Api/Types/Error.hs @@ -30,6 +30,7 @@ module Cardano.Wallet.Api.Types.Error , ApiErrorNotEnoughMoney (..) , ApiErrorNotEnoughMoneyShortfall (..) , ApiErrorMissingWitnessesInTransaction (..) + , ApiErrorNoSuchPool (..) ) where @@ -50,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 (..) ) @@ -152,6 +156,7 @@ data ApiErrorInfo | NetworkUnreachable | NoRootKey | NoSuchPool + !ApiErrorNoSuchPool | NoSuchTransaction | NoSuchWallet | NoUtxosAvailable @@ -299,3 +304,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 diff --git a/lib/integration/framework/Test/Integration/Framework/TestData.hs b/lib/integration/framework/Test/Integration/Framework/TestData.hs index 2d0071b17b7..8306d672986 100644 --- a/lib/integration/framework/Test/Integration/Framework/TestData.hs +++ b/lib/integration/framework/Test/Integration/Framework/TestData.hs @@ -53,7 +53,6 @@ module Test.Integration.Framework.TestData , errMsg403WrongPass , errMsg403WrongMnemonic , errMsg403AlreadyInLedger - , errMsg404NoSuchPool , errMsg403PoolAlreadyJoined , errMsg403NotDelegating , errMsg403NonNullReward @@ -435,10 +434,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 " diff --git a/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/StakePools.hs b/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/StakePools.hs index 8195434788f..6301b0c8500 100644 --- a/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/StakePools.hs +++ b/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/StakePools.hs @@ -53,7 +53,8 @@ import Cardano.Wallet.Api.Types.Amount ( ApiAmount (ApiAmount) ) import Cardano.Wallet.Api.Types.Error - ( ApiErrorInfo (NoUtxosAvailable, PoolAlreadyJoinedSameVote) + ( ApiErrorInfo (NoSuchPool, NoUtxosAvailable, PoolAlreadyJoinedSameVote) + , ApiErrorNoSuchPool (..) ) import Cardano.Wallet.Faucet ( Faucet (..) @@ -221,7 +222,6 @@ import Test.Integration.Framework.TestData , errMsg403NotDelegating , errMsg403PoolAlreadyJoined , errMsg403WrongPass - , errMsg404NoSuchPool , errMsg404NoWallet ) @@ -281,7 +281,10 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do let poolIdAbsent = PoolId $ BS.pack $ replicate 32 1 r <- joinStakePool @n ctx (SpecificPool poolIdAbsent) (w, fixturePassphrase) expectResponseCode HTTP.status404 r - expectErrorMessage (errMsg404NoSuchPool (toText poolIdAbsent)) r + verify r + [ expectErrorInfo $ flip shouldBe $ NoSuchPool $ + ApiErrorNoSuchPool { poolId = poolIdAbsent } + ] it "STAKE_POOLS_JOIN_01 - \ @@ -716,15 +719,17 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do w <- fixtureWallet ctx r <- joinStakePool @n ctx (SpecificPool retiredPoolId) (w, fixturePassphrase) expectResponseCode HTTP.status404 r - expectErrorMessage (errMsg404NoSuchPool (toText retiredPoolId)) r + verify r + [ expectErrorInfo $ flip shouldBe $ NoSuchPool $ + ApiErrorNoSuchPool { poolId = retiredPoolId } + ] it "STAKE_POOLS_JOIN_EMPTY - Empty wallet cannot join a pool" $ \ctx -> runResourceT $ do w <- emptyWallet ctx pool : _ <- map (view #id) <$> notRetiringPools ctx r <- joinStakePool @n ctx (SpecificPool pool) (w, fixturePassphrase) - verify - r + verify r [ expectResponseCode HTTP.status403 , expectErrorInfo (`shouldBe` NoUtxosAvailable) ] @@ -1020,7 +1025,10 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do w <- fixtureWallet ctx r <- liftIO $ joinStakePoolUnsigned @n @'Shelley ctx w (ApiT retiredPoolId) expectResponseCode HTTP.status404 r - expectErrorMessage (errMsg404NoSuchPool (toText retiredPoolId)) r + verify r + [ expectErrorInfo $ flip shouldBe $ NoSuchPool $ + ApiErrorNoSuchPool { poolId = retiredPoolId } + ] describe "STAKE_POOLS_JOIN_UNSIGNED_04" $ it "Cannot join a pool that's never existed" @@ -1039,9 +1047,10 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do w (ApiT non_existing_pool_id) expectResponseCode HTTP.status404 r - expectErrorMessage - (errMsg404NoSuchPool (toText non_existing_pool_id)) - r + verify r + [ expectErrorInfo $ flip shouldBe $ NoSuchPool $ + ApiErrorNoSuchPool { poolId = non_existing_pool_id } + ] it "STAKE_POOLS_QUIT_UNSIGNED_01 - \ diff --git a/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs b/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs index f4d709a0600..afb2db0810a 100644 --- a/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs +++ b/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs @@ -113,6 +113,7 @@ import Cardano.Wallet.Api.Types.Certificate import Cardano.Wallet.Api.Types.Error ( ApiErrorInfo (..) , ApiErrorMissingWitnessesInTransaction (..) + , ApiErrorNoSuchPool (..) , ApiErrorTxOutputLovelaceInsufficient (ApiErrorTxOutputLovelaceInsufficient) ) import Cardano.Wallet.Api.Types.Transaction @@ -329,8 +330,7 @@ import Test.Integration.Framework.DSL , (.>) ) import Test.Integration.Framework.TestData - ( errMsg404NoSuchPool - , errMsg404NoWallet + ( errMsg404NoWallet ) import UnliftIO.Exception ( fromEither @@ -3263,7 +3263,8 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do (Link.createUnsignedTransaction @'Shelley wa) Default delegation verify rTx [ expectResponseCode HTTP.status404 - , expectErrorMessage (errMsg404NoSuchPool (toText absentPoolId)) + , expectErrorInfo $ flip shouldBe $ NoSuchPool $ + ApiErrorNoSuchPool { poolId = absentPoolId } ] it "TRANS_NEW_JOIN_01c - Multidelegation not supported" $ \ctx -> runResourceT $ do diff --git a/lib/primitive/lib/Cardano/Wallet/Primitive/Types/Pool.hs b/lib/primitive/lib/Cardano/Wallet/Primitive/Types/Pool.hs index 9c05e88555a..212d99f288b 100644 --- a/lib/primitive/lib/Cardano/Wallet/Primitive/Types/Pool.hs +++ b/lib/primitive/lib/Cardano/Wallet/Primitive/Types/Pool.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE QuasiQuotes #-} @@ -24,6 +25,9 @@ import Data.ByteArray.Encoding import Data.ByteString ( ByteString ) +import Data.Data + ( Data + ) import Data.List ( intercalate ) @@ -53,7 +57,7 @@ import qualified Data.Text as T -- For Jörmungandr a 'PoolId' is the blake2b-256 hash of the stake pool -- registration certificate. newtype PoolId = PoolId { getPoolId :: ByteString } - deriving (Generic, Eq, Ord) + deriving (Data, Generic, Eq, Ord) instance Show PoolId where show p = "(PoolId " <> show (encodePoolIdBech32 p) <> ")" diff --git a/lib/unit/test/unit/Cardano/Wallet/Api/TypesSpec.hs b/lib/unit/test/unit/Cardano/Wallet/Api/TypesSpec.hs index f3fadac480b..a7a2851707a 100644 --- a/lib/unit/test/unit/Cardano/Wallet/Api/TypesSpec.hs +++ b/lib/unit/test/unit/Cardano/Wallet/Api/TypesSpec.hs @@ -280,6 +280,7 @@ import Cardano.Wallet.Api.Types.Error , ApiErrorNodeNotYetInRecentEra (..) , ApiErrorNotEnoughMoney (..) , ApiErrorNotEnoughMoneyShortfall (..) + , ApiErrorNoSuchPool (..) , ApiErrorSharedWalletNoSuchCosigner (..) , ApiErrorTxOutputLovelaceInsufficient (..) ) @@ -2459,6 +2460,10 @@ instance Arbitrary ApiErrorMessage where arbitrary = genericArbitrary shrink = genericShrink +instance Arbitrary ApiErrorNoSuchPool where + arbitrary = genericArbitrary + shrink = genericShrink + instance Arbitrary ApiErrorMissingWitnessesInTransaction where arbitrary = genericArbitrary shrink = genericShrink From 33997d74ee4bd851c46c4d983ab1351912735a00 Mon Sep 17 00:00:00 2001 From: Jonathan Knowles Date: Wed, 15 May 2024 06:24:02 +0000 Subject: [PATCH 06/17] Reorder imports into alphabetical order. --- lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs | 2 +- lib/unit/test/unit/Cardano/Wallet/Api/TypesSpec.hs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs b/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs index f6ee35bf599..765023d65ef 100644 --- a/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs +++ b/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs @@ -109,10 +109,10 @@ import Cardano.Wallet.Api.Types.Error ( ApiErrorBalanceTxUnderestimatedFee (..) , ApiErrorInfo (..) , ApiErrorMissingWitnessesInTransaction (..) + , ApiErrorNoSuchPool (..) , ApiErrorNodeNotYetInRecentEra (..) , ApiErrorNotEnoughMoney (..) , ApiErrorNotEnoughMoneyShortfall (..) - , ApiErrorNoSuchPool (..) , ApiErrorSharedWalletNoSuchCosigner (..) , ApiErrorTxOutputLovelaceInsufficient (..) ) diff --git a/lib/unit/test/unit/Cardano/Wallet/Api/TypesSpec.hs b/lib/unit/test/unit/Cardano/Wallet/Api/TypesSpec.hs index a7a2851707a..f1e49ae4fba 100644 --- a/lib/unit/test/unit/Cardano/Wallet/Api/TypesSpec.hs +++ b/lib/unit/test/unit/Cardano/Wallet/Api/TypesSpec.hs @@ -277,10 +277,10 @@ import Cardano.Wallet.Api.Types.Error , ApiErrorInfo (..) , ApiErrorMessage (..) , ApiErrorMissingWitnessesInTransaction (..) + , ApiErrorNoSuchPool (..) , ApiErrorNodeNotYetInRecentEra (..) , ApiErrorNotEnoughMoney (..) , ApiErrorNotEnoughMoneyShortfall (..) - , ApiErrorNoSuchPool (..) , ApiErrorSharedWalletNoSuchCosigner (..) , ApiErrorTxOutputLovelaceInsufficient (..) ) From 8f0118b7ab203660b6c2bd3993e493f596a5aeff Mon Sep 17 00:00:00 2001 From: Jonathan Knowles Date: Wed, 15 May 2024 05:43:19 +0000 Subject: [PATCH 07/17] Fix formatting in `IsServerError` instances. --- .../Cardano/Wallet/Api/Http/Server/Error.hs | 41 +++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs b/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs index 765023d65ef..1d5dda02e03 100644 --- a/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs +++ b/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs @@ -642,25 +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 input or withdrawal belonging to the wallet." ] - ErrSubmitTransactionPartiallySignedOrNoSignedTx expectedWitsNo foundWitsNo -> - flip (apiError err403) (mconcat - [ "The transaction expects ", toText expectedWitsNo - , " witness(es) to be fully-signed but ", toText foundWitsNo, " was provided." - , " Submit fully-signed transaction." - ]) $ MissingWitnessesInTransaction - ApiErrorMissingWitnessesInTransaction - { expectedNumberOfKeyWits = fromIntegral expectedWitsNo - , detectedNumberOfKeyWits = fromIntegral foundWitsNo - } + ErrSubmitTransactionPartiallySignedOrNoSignedTx + expectedWitsNo foundWitsNo -> + flip (apiError err403) + (mconcat + [ "The transaction expects " + , toText expectedWitsNo + , " witness(es) to be fully-signed but " + , toText foundWitsNo + , " was provided." + , " Submit fully-signed transaction." + ] + ) $ + MissingWitnessesInTransaction + ApiErrorMissingWitnessesInTransaction + { expectedNumberOfKeyWits = fromIntegral expectedWitsNo + , detectedNumberOfKeyWits = fromIntegral foundWitsNo + } 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." + , "Please use at most one delegation action in a submitted " + , "transaction: join, quit or none." ] instance IsServerError ErrSubmitTx where @@ -733,8 +741,9 @@ instance IsServerError ErrCannotJoin where 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 From 91c5dec1b439cda4a230ad50d2b87732ac785bcb Mon Sep 17 00:00:00 2001 From: Jonathan Knowles Date: Wed, 15 May 2024 05:45:08 +0000 Subject: [PATCH 08/17] Extract out `message` definitions to avoid multi-line parentheses. --- .../Cardano/Wallet/Api/Http/Server/Error.hs | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs b/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs index 1d5dda02e03..32f78e1439b 100644 --- a/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs +++ b/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs @@ -648,21 +648,21 @@ instance IsServerError ErrSubmitTransaction where ] ErrSubmitTransactionPartiallySignedOrNoSignedTx expectedWitsNo foundWitsNo -> - flip (apiError err403) - (mconcat - [ "The transaction expects " - , toText expectedWitsNo - , " witness(es) to be fully-signed but " - , toText foundWitsNo - , " was provided." - , " Submit fully-signed transaction." - ] - ) $ + 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." + , " Submit fully-signed transaction." + ] ErrSubmitTransactionMultidelegationNotSupported -> apiError err403 CreatedMultidelegationTransaction $ mconcat [ "It looks like the transaction to be sent contains" @@ -733,10 +733,13 @@ instance IsServerError ErrCannotJoin where , " joining again would incur an unnecessary fee!" ] ErrNoSuchPool pid -> - flip (apiError err404) (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 - ]) $ NoSuchPool ApiErrorNoSuchPool { poolId = pid } + ] ErrAlreadyDelegatingVoting pid -> apiError err403 PoolAlreadyJoinedSameVote $ mconcat [ "I couldn't join a stake pool with the given id: " From 3d049826fc1c95f371732e8544dedd28439a6665 Mon Sep 17 00:00:00 2001 From: Jonathan Knowles Date: Wed, 15 May 2024 05:47:08 +0000 Subject: [PATCH 09/17] Fix grammar in `IsServerError` instance for `ErrSubmitTransaction`. --- lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs b/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs index 32f78e1439b..625d68acbed 100644 --- a/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs +++ b/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs @@ -644,7 +644,7 @@ instance IsServerError ErrSubmitTransaction where 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." + , "either an input or a withdrawal belonging to the wallet." ] ErrSubmitTransactionPartiallySignedOrNoSignedTx expectedWitsNo foundWitsNo -> @@ -661,12 +661,12 @@ instance IsServerError ErrSubmitTransaction where , " witness(es) to be fully-signed but " , toText foundWitsNo , " was provided." - , " Submit fully-signed transaction." + , " 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." + [ "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." ] From 30f34535af52908e237b0adda13a6e0666c3f217 Mon Sep 17 00:00:00 2001 From: Jonathan Knowles Date: Wed, 15 May 2024 05:52:00 +0000 Subject: [PATCH 10/17] Fix formatting in `Cardano.Wallet.Api.Types.Error`. --- lib/api/src/Cardano/Wallet/Api/Types/Error.hs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/api/src/Cardano/Wallet/Api/Types/Error.hs b/lib/api/src/Cardano/Wallet/Api/Types/Error.hs index 7820c74bd13..e71acb62d3e 100644 --- a/lib/api/src/Cardano/Wallet/Api/Types/Error.hs +++ b/lib/api/src/Cardano/Wallet/Api/Types/Error.hs @@ -280,10 +280,11 @@ data ApiErrorNodeNotYetInRecentEra = ApiErrorNodeNotYetInRecentEra via DefaultRecord ApiErrorNodeNotYetInRecentEra deriving anyclass NFData -data ApiErrorMissingWitnessesInTransaction = ApiErrorMissingWitnessesInTransaction - { expectedNumberOfKeyWits :: Natural - , detectedNumberOfKeyWits :: Natural - } +data ApiErrorMissingWitnessesInTransaction = + ApiErrorMissingWitnessesInTransaction + { expectedNumberOfKeyWits :: Natural + , detectedNumberOfKeyWits :: Natural + } deriving (Data, Eq, Generic, Show, Typeable) deriving (FromJSON, ToJSON) via DefaultRecord ApiErrorMissingWitnessesInTransaction From 796ab421df5e99291beda335766902369953ffd0 Mon Sep 17 00:00:00 2001 From: Jonathan Knowles Date: Wed, 15 May 2024 05:52:53 +0000 Subject: [PATCH 11/17] Add strictness annotations to fields of `ApiErrorMissingWitnessesInTransaction`. --- lib/api/src/Cardano/Wallet/Api/Types/Error.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/api/src/Cardano/Wallet/Api/Types/Error.hs b/lib/api/src/Cardano/Wallet/Api/Types/Error.hs index e71acb62d3e..b0cad3f6ca3 100644 --- a/lib/api/src/Cardano/Wallet/Api/Types/Error.hs +++ b/lib/api/src/Cardano/Wallet/Api/Types/Error.hs @@ -282,8 +282,8 @@ data ApiErrorNodeNotYetInRecentEra = ApiErrorNodeNotYetInRecentEra data ApiErrorMissingWitnessesInTransaction = ApiErrorMissingWitnessesInTransaction - { expectedNumberOfKeyWits :: Natural - , detectedNumberOfKeyWits :: Natural + { expectedNumberOfKeyWits :: !Natural + , detectedNumberOfKeyWits :: !Natural } deriving (Data, Eq, Generic, Show, Typeable) deriving (FromJSON, ToJSON) From e45d2845ddb39ff5e45d0bbad42084a184e6daff Mon Sep 17 00:00:00 2001 From: Jonathan Knowles Date: Wed, 15 May 2024 06:04:19 +0000 Subject: [PATCH 12/17] Add JSON golden test for `ApiErrorMissingWitnessesInTransaction`. --- ...ApiErrorMissingWitnessesInTransaction.json | 45 +++++++++++++++++++ .../test/unit/Cardano/Wallet/Api/TypesSpec.hs | 1 + 2 files changed, 46 insertions(+) create mode 100644 lib/unit/test/data/Cardano/Wallet/Api/ApiErrorMissingWitnessesInTransaction.json diff --git a/lib/unit/test/data/Cardano/Wallet/Api/ApiErrorMissingWitnessesInTransaction.json b/lib/unit/test/data/Cardano/Wallet/Api/ApiErrorMissingWitnessesInTransaction.json new file mode 100644 index 00000000000..6490124950c --- /dev/null +++ b/lib/unit/test/data/Cardano/Wallet/Api/ApiErrorMissingWitnessesInTransaction.json @@ -0,0 +1,45 @@ +{ + "samples": [ + { + "detected_number_of_key_wits": 13, + "expected_number_of_key_wits": 15 + }, + { + "detected_number_of_key_wits": 1, + "expected_number_of_key_wits": 13 + }, + { + "detected_number_of_key_wits": 8, + "expected_number_of_key_wits": 13 + }, + { + "detected_number_of_key_wits": 0, + "expected_number_of_key_wits": 15 + }, + { + "detected_number_of_key_wits": 15, + "expected_number_of_key_wits": 4 + }, + { + "detected_number_of_key_wits": 2, + "expected_number_of_key_wits": 0 + }, + { + "detected_number_of_key_wits": 6, + "expected_number_of_key_wits": 12 + }, + { + "detected_number_of_key_wits": 4, + "expected_number_of_key_wits": 1 + }, + { + "detected_number_of_key_wits": 5, + "expected_number_of_key_wits": 2 + }, + { + "detected_number_of_key_wits": 14, + "expected_number_of_key_wits": 1 + } + ], + "seed": -702842912 +} \ No newline at end of file diff --git a/lib/unit/test/unit/Cardano/Wallet/Api/TypesSpec.hs b/lib/unit/test/unit/Cardano/Wallet/Api/TypesSpec.hs index f1e49ae4fba..1340e89328e 100644 --- a/lib/unit/test/unit/Cardano/Wallet/Api/TypesSpec.hs +++ b/lib/unit/test/unit/Cardano/Wallet/Api/TypesSpec.hs @@ -798,6 +798,7 @@ spec = do jsonTest @ApiEra jsonTest @ApiEraInfo jsonTest @ApiError + jsonTest @ApiErrorMissingWitnessesInTransaction jsonTest @ApiErrorSharedWalletNoSuchCosigner jsonTest @ApiErrorTxOutputLovelaceInsufficient jsonTest @ApiErrorBalanceTxUnderestimatedFee From 3a6a5fda17829e67cd462d48c3e78b446b6c01fe Mon Sep 17 00:00:00 2001 From: Jonathan Knowles Date: Wed, 15 May 2024 06:06:55 +0000 Subject: [PATCH 13/17] Add JSON golden test for `ApiErrorNoSuchPool`. --- .../Wallet/Api/ApiErrorNoSuchPool.json | 35 +++++++++++++++++++ .../test/unit/Cardano/Wallet/Api/TypesSpec.hs | 1 + 2 files changed, 36 insertions(+) create mode 100644 lib/unit/test/data/Cardano/Wallet/Api/ApiErrorNoSuchPool.json diff --git a/lib/unit/test/data/Cardano/Wallet/Api/ApiErrorNoSuchPool.json b/lib/unit/test/data/Cardano/Wallet/Api/ApiErrorNoSuchPool.json new file mode 100644 index 00000000000..93196a5959f --- /dev/null +++ b/lib/unit/test/data/Cardano/Wallet/Api/ApiErrorNoSuchPool.json @@ -0,0 +1,35 @@ +{ + "samples": [ + { + "pool_id": "69b98dd0d2ff323277e4ccef1c2525c9d8b29e0abf6d29d67d818c8e" + }, + { + "pool_id": "3f9c495c3ec62e13c9016afbb22c1e1950983d8bfb8c39675ec77b25" + }, + { + "pool_id": "58c62302ef2a19ec051d7cd3ebe3fb8a491611b0bb05f01a14fedad1" + }, + { + "pool_id": "37b915b5e7f6be14477b14faf3ec374e2398ec54b4f8c755dfd3aa40" + }, + { + "pool_id": "f8e27e563ba531940e0c73c93f5136366b8296c1769047d9e230ec6b" + }, + { + "pool_id": "c54e72492ebb6f97912a41cf4034bf6810004bd75880ffae838be359" + }, + { + "pool_id": "0c907f392b9e5677f2d81f6259de5057df3f001c313b418cf7bb22f1" + }, + { + "pool_id": "9d1ac2a8e6969c85f3126de8c2ec5e0741f278e248da31db33b5daa2" + }, + { + "pool_id": "1f620884c8f64dd34454f6159aa82bdc53275f0d65e3c5a007615cef" + }, + { + "pool_id": "139249a674d3c5883fe3b756a23622745a86b6d3fe5c3b6117229f76" + } + ], + "seed": 1118257763 +} \ No newline at end of file diff --git a/lib/unit/test/unit/Cardano/Wallet/Api/TypesSpec.hs b/lib/unit/test/unit/Cardano/Wallet/Api/TypesSpec.hs index 1340e89328e..1a88d62d2ef 100644 --- a/lib/unit/test/unit/Cardano/Wallet/Api/TypesSpec.hs +++ b/lib/unit/test/unit/Cardano/Wallet/Api/TypesSpec.hs @@ -802,6 +802,7 @@ spec = do jsonTest @ApiErrorSharedWalletNoSuchCosigner jsonTest @ApiErrorTxOutputLovelaceInsufficient jsonTest @ApiErrorBalanceTxUnderestimatedFee + jsonTest @ApiErrorNoSuchPool jsonTest @ApiErrorNodeNotYetInRecentEra jsonTest @ApiErrorNotEnoughMoney jsonTest @ApiFee From 269e95850683d15744225524b5b625cc1aedd654 Mon Sep 17 00:00:00 2001 From: Jonathan Knowles Date: Wed, 15 May 2024 06:10:09 +0000 Subject: [PATCH 14/17] Add API definition for `info` field of `errNoSuchPool`. --- specifications/api/swagger.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/specifications/api/swagger.yaml b/specifications/api/swagger.yaml index 61603d6a3c3..90696ba4457 100644 --- a/specifications/api/swagger.yaml +++ b/specifications/api/swagger.yaml @@ -5193,6 +5193,12 @@ x-errNoSuchPool: &errNoSuchPool code: type: string enum: ['no_such_pool'] + info: + type: object + required: + - pool_id + properties: + pool_id: *stakePoolId x-errPoolAlreadyJoined: &errPoolAlreadyJoined <<: *responsesErr From 701201ab43eee592966a10e9b0c858b87469d6c8 Mon Sep 17 00:00:00 2001 From: Jonathan Knowles Date: Wed, 15 May 2024 06:17:23 +0000 Subject: [PATCH 15/17] Add API definition for `info` field of `errMissingWitnessesInTransaction`. --- specifications/api/swagger.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/specifications/api/swagger.yaml b/specifications/api/swagger.yaml index 90696ba4457..08d9b58c61e 100644 --- a/specifications/api/swagger.yaml +++ b/specifications/api/swagger.yaml @@ -4918,6 +4918,18 @@ x-errMissingWitnessesInTransaction: &errMissingWitnessesInTransaction code: type: string enum: ['missing_witnesses_in_transaction'] + info: + type: object + required: + - detected_number_of_key_wits + - expected_number_of_key_wits + properties: + detected_number_of_key_wits: + type: integer + minimum: 0 + expected_number_of_key_wits: + type: integer + minimum: 0 x-errRejectedByCoreNode: &errRejectedByCoreNode <<: *responsesErr From 1b19aed7b05e526e4517a05050d1acc0606fd680 Mon Sep 17 00:00:00 2001 From: Jonathan Knowles Date: Wed, 15 May 2024 06:39:48 +0000 Subject: [PATCH 16/17] Regenerate JSON golden file for `ApiError`. This is necessary to avoid failures of the following type: ``` src/Test/Aeson/Internal/GoldenSpecs.hs:77:5: 1) Cardano.Wallet.Api.Types, JSON golden roundtrip, JSON encoding of ApiError, produces the same JSON as is found in /home/jsk/projects/input-output-hk/cardano-wallet-0/lib/unit/test/data/Cardano/Wallet/Api/ApiError.json uncaught exception: AesonDecodeError AesonDecodeError "Error in $.samples[14]: parsing Cardano.Wallet.Api.Types.Error.ApiErrorInfo(MissingWitnessesInTransaction) failed, key \"info\" not found" To rerun use: --match "/Cardano.Wallet.Api.Types/JSON golden roundtrip/JSON encoding of ApiError/produces the same JSON as is found in /home/jsk/projects/input-output-hk/cardano-wallet-0/lib/unit/test/data/Cardano/Wallet/Api/ApiError.json/" --seed 1949888530 Randomized with seed 1949888530 ``` The above error appears because we recently added a non-optional `info` field to the `errMissingWitnessesInTransaction` error. --- .../data/Cardano/Wallet/Api/ApiError.json | 1019 ++++++++--------- 1 file changed, 509 insertions(+), 510 deletions(-) diff --git a/lib/unit/test/data/Cardano/Wallet/Api/ApiError.json b/lib/unit/test/data/Cardano/Wallet/Api/ApiError.json index d3fbebdf463..adad3776aa0 100644 --- a/lib/unit/test/data/Cardano/Wallet/Api/ApiError.json +++ b/lib/unit/test/data/Cardano/Wallet/Api/ApiError.json @@ -1,947 +1,946 @@ { "samples": [ { - "code": "balance_tx_existing_return_collateral", - "message": "\u000b\"5o8\u0015󽼴@W" - }, - { - "code": "shared_wallet_key_already_exists", - "message": "B{^o" - }, - { - "code": "wrong_encryption_passphrase", - "message": "𑂾cR\u0017~\u001e\u0016􈦟󸈨EJ𝤽" - }, - { - "code": "rejected_by_core_node", - "message": "􋌂䫬" - }, - { - "code": "inputs_depleted", - "message": "\u0017𗮡M@􌖅\u0010􏑃D\u000c󶘮" + "code": "unsupported_media_type", + "message": "\u0015팟􄸁E􎈳\u0006 o\u001eꞍ" }, { - "code": "unable_to_determine_current_epoch", - "message": "9𰒨󷱈\"Z$󶕘\"\u0014󺻟\u001d|𮋒􁘅" + "code": "transaction_already_balanced", + "message": "󱀇\\cX\u001a'𦃦oR\u0016=􉱨􁚸𩉸" }, { - "code": "node_not_yet_in_recent_era", + "code": "balance_tx_underestimated_fee", "info": { - "node_era": "allegra", - "supported_recent_eras": [ - "alonzo" - ] + "candidate_tx_hex": "", + "candidate_tx_readable": "(", + "estimated_number_of_bootstrap_key_wits": 0, + "estimated_number_of_key_wits": 2, + "underestimation": { + "quantity": 19770424347101868, + "unit": "lovelace" + } }, - "message": "\"\u00019y雍\u0013󰨴\u0012m" + "message": "T𤢸sM\u001ba󵵩I" }, { - "code": "key_not_found_for_address", - "message": "􊉿󴔗;\r" - }, - { - "code": "tx_not_in_node_era", - "message": "󼑗@𢽹\nMp\u001b􋺎𮌬𤌉Lf" - }, - { - "code": "balance_tx_internal_error", - "message": "{o\u0000􉕬q" + "code": "rejected_by_core_node", + "message": "t>Vc\u0004" }, { - "code": "missing_reward_account", - "message": "!g𐒰!󹕝\u0003E" + "code": "created_wrong_policy_script_template", + "message": "S𫥋`" }, { - "code": "past_horizon", - "message": "\u001a" + "code": "not_implemented", + "message": "H󻻡6]" }, { - "code": "created_multiaccount_transaction", - "message": "B" + "code": "validity_interval_not_inside_script_timelock", + "message": "\u000e&/`#\u001cIP\u0011䳓w" }, { - "code": "nothing_to_migrate", - "message": "󴹭󷬂[\u0000𬎔𭀚" + "code": "transaction_already_in_ledger", + "message": "s\u001f\r\u0001_𤭘T)l𰛞𤌿􎭉^;" }, { - "code": "missing_witnesses_in_transaction", - "message": "曄*\u0010\u0019,(􆈖4Fo$𰂣" + "code": "non_null_rewards", + "message": "f\\p_쩧J" }, { - "code": "output_token_bundle_size_exceeds_limit", - "message": "$Z=P󷒍𘎀hk" + "code": "past_horizon", + "message": "b\u0002\\=Nl8Y" }, { - "code": "balance_tx_conflicting_networks", - "message": "\n􃇸\u0008\u001c)\"" + "code": "shared_wallet_incomplete", + "message": "stA\u000eJ[{幬" }, { "code": "input_resolution_conflicts", - "message": "Zrr𠈹" + "message": "􃄕𬕲du5" }, { - "code": "soft_derivation_required", - "message": "" + "code": "shared_wallet_script_template_invalid", + "message": "eH\u0014\u0016􅄲㛼\t𬉕E;" }, { - "code": "transaction_already_balanced", - "message": "\nJ𨔽Q]𣄁" + "code": "unexpected_error", + "message": "𧚔𪊯􀈔-}􀲕D" }, { - "code": "shared_wallet_no_such_cosigner", - "info": { - "cosigner_index": 6, - "credential_type": "payment" - }, - "message": "[SDC{2" + "code": "balance_tx_existing_total_collateral", + "message": "3𤘘7t|a" }, { "code": "utxo_too_small", "info": { - "tx_output_index": 0, + "tx_output_index": 1, "tx_output_lovelace_required_minimum": { "quantity": 0, "unit": "lovelace" }, "tx_output_lovelace_specified": { - "quantity": 22345494713847260, + "quantity": 19932530910944474, "unit": "lovelace" } }, - "message": "\u0013𱋹\u0015𱉷󷻝⋝􄠨" + "message": "󼠎팚" }, { - "code": "unable_to_determine_current_epoch", - "message": "" + "code": "input_resolution_conflicts", + "message": ",N\u0003~\u001a󹝭􆔚s݁H􀂮6A0" }, { - "code": "missing_reward_account", - "message": "" + "code": "hardened_derivation_required", + "message": "󶘥\u0001𖽝i\u000e9" }, { - "code": "wrong_encryption_passphrase", - "message": "uTl" + "code": "query_param_missing", + "message": "GqgK𑤡𱅁" }, { - "code": "malformed_tx_payload", - "message": "`H%{􃪒𪳎\u0007\u0018𧾀󸓋\u0000C" + "code": "network_query_failed", + "message": "𰭼􎨆" }, { - "code": "balance_tx_underestimated_fee", + "code": "shared_wallet_no_such_cosigner", "info": { - "candidate_tx_hex": "", - "candidate_tx_readable": "(", - "estimated_number_of_bootstrap_key_wits": 0, - "estimated_number_of_key_wits": 0, - "underestimation": { - "quantity": 11458904746561377, - "unit": "lovelace" - } + "cosigner_index": 6, + "credential_type": "delegation" }, - "message": "󹣕\u001d\u0017􌂿\r𬌰󰒖\u0014𥰑X" + "message": "4 k󿝭L]4:𥊐ﵱa" }, { - "code": "utxo_too_small", - "info": { - "tx_output_index": 0, - "tx_output_lovelace_required_minimum": { - "quantity": 0, - "unit": "lovelace" - }, - "tx_output_lovelace_specified": { - "quantity": 18388597842438056, - "unit": "lovelace" - } - }, - "message": "󸄱􆦞󿘹\u0006q7?a󳤓" + "code": "asset_not_present", + "message": "g`v𪜕OO2L蒞g" }, { - "code": "unexpected_error", - "message": "\u001b(;\u000e" + "code": "redeemer_target_not_found", + "message": "㬩6]l\u001b>󱠝" }, { - "code": "not_implemented", - "message": ":\u000f􃍭\u0019󵣶@\u0017R" + "code": "malformed_tx_payload", + "message": "n" }, { - "code": "bad_request", - "message": "Y]𣋭󿹫]󴾉M𧭥\u0003M" + "code": "output_token_bundle_size_exceeds_limit", + "message": "\\d􉽜" }, { - "code": "start_time_later_than_end_time", - "message": "􍞚" + "code": "shared_wallet_cannot_update_key", + "message": "[⾣<ꎆ4paf\u0013Uq𐓋|" }, { - "code": "unable_to_determine_current_epoch", - "message": "\u0015GH,*𧁳𠻣@J8􂜖𐃮" + "code": "wrong_mnemonic", + "message": "\u001fi8𤇁⋥-]􌇂󳃰" }, { - "code": "wrong_encryption_passphrase", - "message": "\u0003Xt\u0015Qno" + "code": "insufficient_collateral", + "message": "`\u0005v𒇺𝘼m4V{" }, { - "code": "no_such_pool", - "message": "\u0004I󱈩𰘓\u0013󺸇𭽈p\u0011\u001f𪻞􄥨7C" + "code": "missing_reward_account", + "message": "P&.\u001d]𤖬y`o𨙨'V$" + }, + { + "code": "unsupported_media_type", + "message": "\u0017\u0007󴊇󹎦" }, { "code": "no_such_wallet", - "message": "\t\"R􌑪\u0018\u0014J𠛮\u001fI\t" + "message": "c]ࠓ*𓁽𱖿\u001e⛥%v]\u0001" }, { - "code": "foreign_transaction", - "message": "!󽪑S󽸽\u0019\u000ftO?S9P􍑿𧗄" + "code": "insufficient_collateral", + "message": "𗯥n\u000c" }, { - "code": "withdrawal_not_beneficial", - "message": "ᕚ" + "code": "existing_key_witnesses", + "message": "앆󿍭\u0007" }, { - "code": "wallet_metadata_not_found", - "message": "\u0018Qc󻷂Z𥓚#\u0011" + "code": "cannot_cover_fee", + "message": "Y秂" }, { - "code": "address_already_exists", - "message": "ἏL󼦦𓐅y.􉏳'" + "code": "redeemer_target_not_found", + "message": "\u0011鯧2\u001fy)(s+" }, { - "code": "non_null_rewards", - "message": "󺕠 \u001b\u001c\u0003R󸱬Up􄻾$\u0018" + "code": "shared_wallet_incomplete", + "message": "e\u0013K􋉫x8\u000c>\u0010TS\u0003" }, { - "code": "created_invalid_transaction", - "message": "Vẟ<#p" + "code": "node_not_yet_in_recent_era", + "info": { + "node_era": "byron", + "supported_recent_eras": [ + "babbage", + "alonzo" + ] + }, + "message": "𧰏@qs𬤻DL\u0017􆊛'" }, { - "code": "network_unreachable", - "message": "/\u0018DjA\u0003젞Rf3􈘺%" + "code": "withdrawal_not_possible_without_vote", + "message": "􆺮-\u000b𧥬v~j󴂙}6<\u0003l" }, { - "code": "malformed_tx_payload", - "message": "8𑚖" + "code": "output_token_quantity_exceeds_limit", + "message": "먆𛊊?bi(𩟹󶂟𞴈" }, { - "code": "transaction_already_balanced", - "message": "a𩝃^y􆹣hs" + "code": "balance_tx_internal_error", + "message": "\u0003;xX􉶄" }, { - "code": "key_not_found_for_address", - "message": "Mn􃒵𡭪HI$𤖜," + "code": "asset_not_present", + "message": "" + }, + { + "code": "missing_reward_account", + "message": "\u000c\u0015\u0008u" + }, + { + "code": "cannot_cover_fee", + "message": "􆹕$m\u0010KA󰁸]a" }, { "code": "query_param_missing", - "message": "" + "message": "IM*𮙸􋀁>\u001bn<\u001eYG" }, { - "code": "validity_interval_not_inside_script_timelock", - "message": "𔔻)" + "code": "not_synced", + "message": "􊼺;" }, { - "code": "foreign_transaction", - "message": "zf󰃉𦥷fH󱙽B-" + "code": "wallet_metadata_not_found", + "message": "$8:})󷶿_9􀄫\u0007}9B" }, { - "code": "shared_wallet_script_template_invalid", - "message": "r" + "code": "soft_derivation_required", + "message": "\u0001x󷗏Oi\u0012h󼼎]" }, { - "code": "balance_tx_existing_total_collateral", - "message": "F9󽼰𱅪" + "code": "created_multidelegation_transaction", + "message": "\\\rk_JzT" }, { - "code": "not_found", - "message": "𬢉W=󱪕>󶩝\u001a󻯬8𠿃" + "code": "node_not_yet_in_recent_era", + "info": { + "node_era": "allegra", + "supported_recent_eras": [ + "byron", + "alonzo", + "byron", + "babbage" + ] + }, + "message": "0" }, { - "code": "insufficient_collateral", - "message": "𨶙\u0007悋\u000f#O!L" + "code": "no_such_wallet", + "message": "󱹯𘄂cq󳊹D" }, { - "code": "balance_tx_existing_total_collateral", - "message": "e\u001c𢉑\u0007\"\u0004w𣧥(\u0001\u0000!" + "code": "past_horizon", + "message": "𫗙󴰵󿂷\u0007z~i" }, { - "code": "not_acceptable", - "message": "g\noW\u0003M6\u0007rQ" + "code": "malformed_tx_payload", + "message": "GᎵ0ZC𐚻$4\"a\u0012" }, { - "code": "invalid_wallet_type", - "message": "\u000c" + "code": "rejected_by_core_node", + "message": "\u0016*􁠥n]\u0005*\u0006rpM" }, { - "code": "mempool_is_full", - "message": "'t􂭷󻛴@" + "code": "unable_to_determine_current_epoch", + "message": "\u000fF\t\u0008\u0014􃼐o󺐕|)A^" }, { - "code": "delegation_invalid", - "message": "\u001eKg󳪎v󿣲\u001d>􉮶\u000b0" + "code": "network_query_failed", + "message": "*D" }, { - "code": "network_misconfigured", - "message": "𠐣NDgڞ\u001afx󱂖5" + "code": "not_delegating_to", + "message": "0X􁂸𥕝!+^E\t\n" }, { - "code": "balance_tx_internal_error", - "message": "lu뺣𓂐8sb-o𡦩" + "code": "min_withdrawal_wrong", + "message": " \\Ay\u0011\u0014" }, { - "code": "missing_reward_account", - "message": "􂿀e" + "code": "redeemer_script_failure", + "message": "𢃲" }, { - "code": "malformed_tx_payload", - "message": "\u000e" + "code": "method_not_allowed", + "message": "wO%\u001f\u0014\u00010󵡖VA" }, { - "code": "withdrawal_not_beneficial", - "message": "\u0019\u0016 t2h󽊅-W" + "code": "voting_in_invalid_era", + "message": "􅵯I)󳩂󻤁𧎥j3Z𮀣󱔰W" }, { - "code": "redeemer_target_not_found", - "message": "\u000bcg\u000fSv󽿿&ye\r₠b繚" + "code": "wallet_already_exists", + "message": "\u001e\u00073=\u001f4󽊼𐅯\n\"𨗁" }, { - "code": "start_time_later_than_end_time", - "message": "􀸺h>8" + "code": "cannot_cover_fee", + "message": "⻙" }, { - "code": "mempool_is_full", - "message": "3E𭋘\\󸡼$'󲆨" + "code": "node_not_yet_in_recent_era", + "info": { + "node_era": "byron", + "supported_recent_eras": [ + "mary", + "babbage", + "byron", + "byron", + "babbage" + ] + }, + "message": "\u0010􋔫'`\u0006t󹁺𰡅|pB" }, { - "code": "wrong_mnemonic", - "message": "\u0002~ 귍3L=ij󾊶􇙷\u0008୴\u001f" + "code": "pool_already_joined_same_vote", + "message": ";\u0018𮃁hy" }, { - "code": "delegation_invalid", - "message": ")-𠞸c]aR" + "code": "same_vote", + "message": "\nd󾇢Y𦌕\u0013D𒒒骲k" }, { - "code": "not_delegating_to", - "message": "C𬍉\u0008\n\u0019y\u0013+^\u000b𛋡𰎌3&" + "code": "address_already_exists", + "message": "/vY␟\u0007" }, { - "code": "shared_wallet_key_already_exists", - "message": "󷭱" + "code": "already_withdrawing", + "message": "/I􎁂OE0󲅵A$\u001di\u0019f" }, { - "code": "no_such_pool", - "message": "\n\u0005" + "code": "block_header_not_found", + "message": "=" }, { - "code": "shared_wallet_script_template_invalid", - "message": "󶓏e" + "code": "no_root_key", + "message": "SpS辪\u001f\u0019 " }, { - "code": "invalid_validity_bounds", - "message": "O[U𣺖" + "code": "unable_to_determine_current_epoch", + "message": "\u0013\u0005,𬳭𱑪$ai" }, { - "code": "created_invalid_transaction", - "message": "𦯶;󻥒|\u0006𨡛𗱺o" + "code": "existing_key_witnesses", + "message": "7󳛇@\u000e@\"\u0006썞" }, { - "code": "min_withdrawal_wrong", - "message": "aZ󽭌k1􌅿x" + "code": "insufficient_collateral", + "message": "<𭗂\u001f7\u0013𮰥" }, { - "code": "shared_wallet_script_template_invalid", - "message": "oLY\u00169m<#𤓮 \u0017|" + "code": "balance_tx_existing_total_collateral", + "message": ":𬩺\u0002V9淺~T𢷁t\u001f\u0010\u0019" }, { - "code": "unsupported_media_type", - "message": "<􀳋\u0008y\u001b{U󸧆\u0004\u0016󾢭\u000c)" + "code": "insufficient_collateral", + "message": "i*a󲆒K*\u001aG𤜊𫼘[𦛢x" }, { - "code": "invalid_coin_selection", - "message": "\u0008\u0017\u001d󽀝𢦝􈭫V\u0001" + "code": "unexpected_error", + "message": "G盼\u0019🥧Si\u0001𡣕" }, { - "code": "created_invalid_transaction", + "code": "redeemer_target_not_found", + "message": "0ettXv󸗵\u001f𢏞X𢡐{" + }, + { + "code": "translation_byron_tx_out_in_context", "message": "\u0007" }, { - "code": "wrong_mnemonic", - "message": "A󰯎딼){e󷮛􌥧뿳𤪜 \"R" + "code": "invalid_wallet_type", + "message": "􏻯\u0008(Fo􁖼#95" }, { - "code": "redeemer_target_not_found", - "message": "𖤯tB\u0010󾤹쉛P/h" + "code": "tx_not_in_node_era", + "message": "\u001b痰\u001cず𭼱𞲜\"" }, { - "code": "not_enough_money", + "code": "node_not_yet_in_recent_era", "info": { - "shortfall": { - "ada": { - "quantity": 0, - "unit": "lovelace" - }, - "assets": [ - { - "asset_name": "0000000100000001010000010000010100000001010001000100010101000001", - "policy_id": "01000001010000000100000000000101010100000100000000000100", - "quantity": 0 - } - ] - } + "node_era": "babbage", + "supported_recent_eras": [ + "allegra", + "babbage", + "allegra", + "allegra", + "shelley", + "babbage" + ] }, - "message": "{􀀝\\󺀊" + "message": ":\u0016􇑲m" }, { - "code": "hardened_derivation_required", - "message": "[3󲣰d\u0010􀢯_q싶`󺨜8" + "code": "shared_wallet_incomplete", + "message": "|y=}\u000cb󸺖󵿤鼔A\u0008" }, { - "code": "missing_witnesses_in_transaction", - "message": "@􀳡_=l\u001d\u001d󲣖UD(🙤\u000b" + "code": "block_header_not_found", + "message": "\"~" }, { - "code": "balance_tx_conflicting_networks", - "message": "𡴤呋" + "code": "shared_wallet_incomplete", + "message": "z\u000f󱳦:Z𧈶謰48􂆕悯" }, { - "code": "invalid_validity_bounds", - "message": ")eK䦶󵞀ER\u000ep􀥫\u0018&亲" + "code": "output_token_quantity_exceeds_limit", + "message": "𤐍&V'f" }, { - "code": "no_utxos_available", - "message": "(`" + "code": "created_multidelegation_transaction", + "message": " zb+󲨁\u0005󹈞􌔖󴝰" }, { "code": "balance_tx_existing_key_witnesses", - "message": "rn󱤂,\u0014\u000f𐅓)󵩛􂬟" - }, - { - "code": "redeemer_invalid_data", - "message": "􏿧\u001aq&D;\u000b𥝋C" + "message": ">M 𪷮:\u0013\u001bJX`\u001d􉖯" }, { - "code": "asset_name_too_long", - "message": "oB+󷖡蝟\u001f𰶻\u0017(T" + "code": "block_header_not_found", + "message": "Ae|X+\"i|Z6" }, { - "code": "redeemer_target_not_found", - "message": "\t󾘲g'󿢨럞e&3􂻻1𥴍" + "code": "not_synced", + "message": "Xp*" }, { - "code": "balance_tx_internal_error", - "message": "Q􎎡%􇵜" + "code": "mempool_is_full", + "message": "\r\u0010r*!D\r$[B􇢓󵝖" }, { - "code": "validity_interval_not_inside_script_timelock", - "message": "𢰖𡌕" + "code": "no_utxos_available", + "message": "\u0018􍬜\n􄫏W" }, { - "code": "inputs_depleted", - "message": "\u000e󰐭𡰕𧎶" + "code": "unsupported_media_type", + "message": "K]" }, { - "code": "tokens_minted_but_not_spent_or_burned", - "message": "󳊦𣰱T[C焓󾋒􈐪\u0005c" + "code": "unresolved_inputs", + "message": "{,3" }, { - "code": "balance_tx_underestimated_fee", + "code": "no_such_pool", "info": { - "candidate_tx_hex": "\u0013", - "candidate_tx_readable": "", - "estimated_number_of_bootstrap_key_wits": 1, - "estimated_number_of_key_wits": 0, - "underestimation": { - "quantity": 4843387493497409, - "unit": "lovelace" - } + "pool_id": "2a291332313210231022320c3333233c10051a393017323c082d3e0f" }, - "message": "\u0011#$*:󳽱{\u0000\ruC󰯁|r" + "message": "\u001c\u0014\u001a󸫻Q\u0000\u0014m[2}k𰷕􇗻" }, { - "code": "soft_derivation_required", - "message": "\u000b\u0013}#,\\蟂M\"}" + "code": "query_param_missing", + "message": "V5\"󹁨\u000cz𥜾Yw)􃫖" }, { - "code": "insufficient_collateral", - "message": "J|" + "code": "not_implemented", + "message": "" }, { - "code": "method_not_allowed", - "message": "e" + "code": "hardened_derivation_required", + "message": "xﮎ" }, { - "code": "invalid_validity_bounds", - "message": "\u001d" + "code": "cannot_cover_fee", + "message": "~k[a\u0011" }, { - "code": "bad_request", - "message": "󽰿+|>\u000b󸪺􁗳" + "code": "unsupported_media_type", + "message": "5X" }, { - "code": "unexpected_error", - "message": "0\u0010:\rr~" + "code": "wallet_not_responding", + "message": "􇤐_gb3t\u0005`" }, { - "code": "foreign_transaction", - "message": "" + "code": "shared_wallet_no_such_cosigner", + "info": { + "cosigner_index": 5, + "credential_type": "payment" + }, + "message": "]7" }, { - "code": "not_implemented", - "message": "/󲅞$c-ϰ0􍱎ZU\u0014󹉹" + "code": "withdrawal_not_beneficial", + "message": "t\u0017𫂡𩂗H\u0006d\u0006𢧑a'iP󳥑" }, { - "code": "unsupported_media_type", - "message": "𮃹8𐔳u}-𭗕" + "code": "no_such_wallet", + "message": "\u001c\u0011" }, { - "code": "missing_policy_public_key", - "message": "伿,8+z༲[" + "code": "pool_already_joined_same_vote", + "message": "\u0000􉅉d\u0013e" }, { - "code": "not_found", - "message": "୵𩣾엗A" + "code": "mempool_is_full", + "message": "{A𬭖\u0008\u0017y􎝺" }, { - "code": "past_horizon", - "message": "󹁢u󲃮\t\u0018uDH" + "code": "created_multiaccount_transaction", + "message": ">L毌q𣊺S󳥪藯𤡽b" }, { - "code": "translation_error", - "message": "p3J}R*𥙓\u000e󻙀듾2" + "code": "key_not_found_for_address", + "message": "􄿘2$C)c𝛤\u000e𡠤\u0012\u001d\u0004󾳃" }, { - "code": "delegation_invalid", - "message": "D?P\u0008" + "code": "redeemer_script_failure", + "message": "" }, { - "code": "tokens_minted_but_not_spent_or_burned", - "message": "26>\u0011𧳃c+􉽯R" + "code": "created_invalid_transaction", + "message": "􂰲;p~kWn" }, { - "code": "balance_tx_existing_key_witnesses", - "message": "" + "code": "mempool_is_full", + "message": "􃩂*Asz" }, { - "code": "wrong_mnemonic", - "message": "X" + "code": "network_unreachable", + "message": "{J" }, { - "code": "balance_tx_existing_total_collateral", - "message": "𰄳wNes󻁭\u0014󱜫\u0018" + "code": "query_param_missing", + "message": "3Z5" }, { "code": "not_delegating_to", - "message": "\u0000IY)NC碖R\u00060" + "message": "h" }, { - "code": "not_synced", - "message": "z~\"𒀞1\u0008" + "code": "shared_wallet_cannot_update_key", + "message": "揱\u000f􎅾ᬈ" }, { - "code": "not_found", - "message": "aD\u0000𭡶]\u0011\u0019p~𫢔" + "code": "translation_error", + "message": "sEB%𫛷駏'" }, { - "code": "output_token_bundle_size_exceeds_limit", - "message": "\r}锒Ne\u0006O" + "code": "rejected_by_core_node", + "message": "" }, { - "code": "withdrawal_not_beneficial", - "message": "+େ+" + "code": "not_synced", + "message": "CZ\u0016g#9\u0002𛄠`I" + }, + { + "code": "redeemer_target_not_found", + "message": "\u0010F~YQj􆩋󹵄𝁟\u0005\u001d" }, { - "code": "no_such_transaction", - "message": "𫋮\u001c\u0000]O荙{*󽆾k" + "code": "balance_tx_existing_total_collateral", + "message": "m󻙞3/\t" }, { - "code": "no_such_pool", - "message": "\u0004:O^\u0007*V(#\t==𪝘" + "code": "not_found", + "message": "%HP\u0002yz󴥸\t𣨝𩴗)\"E\u001c" }, { - "code": "not_enough_money", + "code": "network_unreachable", + "message": "𝨃\\\u0019X党=l(㷊" + }, + { + "code": "utxo_too_small", "info": { - "shortfall": { - "ada": { - "quantity": 0, - "unit": "lovelace" - }, - "assets": [] + "tx_output_index": 0, + "tx_output_lovelace_required_minimum": { + "quantity": 20663996575782212, + "unit": "lovelace" + }, + "tx_output_lovelace_specified": { + "quantity": 32782666421279309, + "unit": "lovelace" } }, - "message": "Yd:j?\u0013i" + "message": "`6<" }, { - "code": "malformed_tx_payload", - "message": "Jk􁘱\u0014A" + "code": "voting_in_invalid_era", + "message": "\u0001^흌\u0012/\u0004🁷K|􈍍" }, { - "code": "balance_tx_existing_collateral", - "message": "NK\u0011\u0016E<" + "code": "translation_error", + "message": "\u0005,󱈨\u0003.m=𫜍!D%>᪫" }, { - "code": "insufficient_collateral", - "message": "V𘡍Q" + "code": "shared_wallet_no_such_cosigner", + "info": { + "cosigner_index": 3, + "credential_type": "delegation" + }, + "message": "%7𧱗􍩙𠃃t06|𔓂I}𭏙" }, { - "code": "shared_wallet_key_already_exists", - "message": "" + "code": "created_invalid_transaction", + "message": "\rx" }, { - "code": "network_unreachable", - "message": "" + "code": "created_multidelegation_transaction", + "message": "v4r𠞭}8𡹆>\u0000*R1Yv" }, { - "code": "created_multiaccount_transaction", - "message": "]" + "code": "created_multidelegation_transaction", + "message": "5𧗔}W{󸨆𮧱S_􅚎" }, { - "code": "missing_reward_account", - "message": "\u0005qSR𥥉_􈜤.)󹏳Y" + "code": "output_token_quantity_exceeds_limit", + "message": "􁮞&x(𢾽􂘎𮸆㤂" }, { - "code": "balance_tx_conflicting_networks", - "message": "𮩪59+{Vbj􋆠" + "code": "shared_wallet_key_already_exists", + "message": "!]􍨵M'󷴒\u0014" }, { - "code": "unexpected_error", - "message": "8'" + "code": "asset_not_present", + "message": "\u000bs\u0017#S\u000c9J\u000b\u001d_􉳪" }, { - "code": "created_multiaccount_transaction", - "message": "2P@𗇥\u00132\u0017𭵭󰎫?\u001a" + "code": "invalid_coin_selection", + "message": "𥰢ka.􋍣nhI𩭧o􎈌鉶" }, { - "code": "mempool_is_full", - "message": "\u0006^k\u0000\u000cuj𨥰T" + "code": "balance_tx_internal_error", + "message": "􀰙wk\u001c" }, { - "code": "shared_wallet_script_template_invalid", - "message": "" + "code": "min_withdrawal_wrong", + "message": "r`<\u0010邌k^x/AꂯCI" + }, + { + "code": "hardened_derivation_required", + "message": "\u0017DA􀃲󼠃\u0000" }, { "code": "balance_tx_conflicting_networks", - "message": "🎣󳘚8b疵䐋" + "message": "/}􍸅𧴿𛰼v" }, { - "code": "wallet_not_responding", - "message": "+\u0007􅥢o" + "code": "not_synced", + "message": "%э*檆\u0013_𥼠\u0006\u0014𖽈银K\u001fꐒ" }, { - "code": "delegation_invalid", - "message": "" + "code": "missing_reward_account", + "message": " D𗭍=\u000fk\u0015f䔯m6oKW" }, { - "code": "mempool_is_full", - "message": "*y(ਡ󱀊wⅢX" + "code": "missing_policy_public_key", + "message": "'s􀸱\tIU\u001fuA" }, { - "code": "created_multidelegation_transaction", - "message": "" + "code": "no_utxos_available", + "message": "햧,𭚗" }, { - "code": "shared_wallet_active", - "message": "ww𧺩J5]" + "code": "not_synced", + "message": "@\u0008𣤼#𩹥/\u0016蓯" }, { - "code": "shared_wallet_key_already_exists", - "message": "4\u0006f󾸏9%" + "code": "not_implemented", + "message": "󷥉Tx\u0006bIyi鞈0􍘄󹛵󼅊Syl㟬󿐩\u0002󱴎6" }, { - "code": "redeemer_target_not_found", - "message": "" + "code": "wallet_metadata_not_found", + "message": "\u0012p􇜷󰈁" }, { - "code": "tx_not_in_node_era", - "message": "𭖄" + "code": "delegation_invalid", + "message": ":b𝗀iJW\u0013z󴌆bW铹㸆" }, { - "code": "output_token_bundle_size_exceeds_limit", - "message": "5𰊆h쒏d𦸄󱚫\n𰣋" + "code": "not_found", + "message": "\u0006\u0006G|" }, { - "code": "pool_already_joined", - "message": "jL\u001d\u001cFM\u000c9袠" + "code": "transaction_already_balanced", + "message": "c\u0005 뮁𗯴\t\u000eg^\u001eg$\u00135" }, { - "code": "already_withdrawing", - "message": "撔Q@[L" + "code": "validity_interval_not_inside_script_timelock", + "message": "U𓉆{𱁇\u0005" }, { - "code": "balance_tx_underestimated_fee", - "info": { - "candidate_tx_hex": "󿫯", - "candidate_tx_readable": "\u0001󹾰", - "estimated_number_of_bootstrap_key_wits": 1, - "estimated_number_of_key_wits": 0, - "underestimation": { - "quantity": 8867148595489306, - "unit": "lovelace" - } - }, - "message": "4\"\u001c𢨵=ZB" + "code": "unable_to_assign_input_output", + "message": "&]:\u0012p0VD" }, { - "code": "tx_not_in_node_era", - "message": "i􂇦JA" + "code": "created_multidelegation_transaction", + "message": "dm!H" }, { - "code": "withdrawal_not_beneficial", - "message": "\\+$\u001b%壓􆡑xc\u0003" + "code": "redeemer_target_not_found", + "message": "\u000eH}`4C!󿣚r\\𗪖𓅡t􁁋" }, { - "code": "wrong_encryption_passphrase", - "message": "k}" + "code": "inputs_depleted", + "message": "wL`𣵯\u0014K\u0008YT\u0015" }, { - "code": "network_unreachable", - "message": "\u000f\u000e\t" + "code": "translation_byron_tx_out_in_context", + "message": "&" }, { - "code": "unable_to_determine_current_epoch", - "message": "𠽅e𑢮햮𪃐N-𧂞bs" + "code": "not_synced", + "message": "$C" }, { - "code": "utxo_too_small", + "code": "delegation_invalid", + "message": "􌳷nv," + }, + { + "code": "node_not_yet_in_recent_era", "info": { - "tx_output_index": 0, - "tx_output_lovelace_required_minimum": { - "quantity": 45000000000000000, - "unit": "lovelace" - }, - "tx_output_lovelace_specified": { - "quantity": 18855340161094467, - "unit": "lovelace" - } + "node_era": "allegra", + "supported_recent_eras": [ + "allegra", + "mary", + "mary" + ] }, - "message": "U\\x\"C⺢" + "message": "8𣦡{YO+\\\u0006K" }, { - "code": "created_multiaccount_transaction", - "message": "ⱪT" + "code": "balance_tx_existing_return_collateral", + "message": "`D" }, { - "code": "translation_error", - "message": "CC" + "code": "redeemer_invalid_data", + "message": "Y" }, { - "code": "shared_wallet_cannot_update_key", - "message": "%\u0000@_P𠙔)F" + "code": "hardened_derivation_required", + "message": "" }, { - "code": "shared_wallet_incomplete", - "message": "VE𫫝\u0008\u0003T\u0010􎆅lbE" + "code": "translation_error", + "message": "+􈙙𠠵s\u0001襴0.y" }, { - "code": "min_withdrawal_wrong", - "message": "4}d𨹾" + "code": "start_time_later_than_end_time", + "message": "" }, { - "code": "nothing_to_migrate", - "message": "Q𒒑𗿀𥦏\u0010󳖴%]_.C" + "code": "created_multidelegation_transaction", + "message": "*\n𰄢| p{s􌸹𲈷" }, { - "code": "method_not_allowed", - "message": "8[v󱺛" + "code": "created_multiaccount_transaction", + "message": "krベ\u0014𩝤~𦲐^\u0003􏷏" }, { - "code": "start_time_later_than_end_time", - "message": "\n]Q$󶑕OX󴋟8􄛲\u001b>" + "code": "missing_reward_account", + "message": "褔[n}G?M\u0002𱎾5" }, { - "code": "invalid_validity_bounds", - "message": "+,\u000e" + "code": "no_utxos_available", + "message": "'𮶂#𓂨 " }, { - "code": "balance_tx_existing_return_collateral", - "message": "󳣙􀎵Y𩸤\u00148w" + "code": "missing_witnesses_in_transaction", + "info": { + "detected_number_of_key_wits": 7, + "expected_number_of_key_wits": 2 + }, + "message": "\u0006`1Gd" }, { - "code": "existing_key_witnesses", - "message": "쪋󿗻" + "code": "created_wrong_policy_script_template", + "message": "VnPNES􄳟b\u0004%󳉢/" }, { - "code": "bad_request", - "message": "/X\u001e\u0003󴰔2𫊿" + "code": "query_param_missing", + "message": "𘎶𐾺M" }, { - "code": "no_such_pool", - "message": "J\u001e뒵Ei" + "code": "balance_tx_conflicting_networks", + "message": "o󾌞\t27\u0002짛𢯛" }, { - "code": "already_withdrawing", - "message": "\u0007\u0018Cn8宏\u0016󺰻\u0015" + "code": "balance_tx_inline_plutus_v3_script_not_supported_in_babbage", + "message": "\t𤋬󽒶Kc}\u0019𭸤\"𩱍􋛟h" }, { - "code": "cannot_cover_fee", - "message": "&\u001f2\u000b" + "code": "missing_policy_public_key", + "message": "\u0005\u001eN^+ILZ" }, { - "code": "method_not_allowed", - "message": "8􂣬L🠀\u000e𬅋􉼷󺫉]" + "code": "node_not_yet_in_recent_era", + "info": { + "node_era": "alonzo", + "supported_recent_eras": [] + }, + "message": "|𤽸0n" }, { "code": "not_enough_money", "info": { "shortfall": { "ada": { - "quantity": 19194419887079638, + "quantity": 29203954436170393, "unit": "lovelace" }, "assets": [ { - "asset_name": "0000010101000000010000010100010000010101010101010000010100000001", - "policy_id": "01010101010001010101010101010100000100000101010100000101", + "asset_name": "0001010101000001000000010000010100010000000101000000010001000100", + "policy_id": "00010101010101010001010001010101010101000101010000010001", "quantity": 1 }, { - "asset_name": "0000000001010100000100010001000000010000010000000000010001000101", - "policy_id": "01000101000000000101000100010001010101000101000001000001", - "quantity": 0 + "asset_name": "0100000000010000010101010000010101000101010000000001000101000000", + "policy_id": "00000100010000000101000101000001000100010001000001010001", + "quantity": 1 }, { - "asset_name": "0000010000010000010001000000000000010100000100000001000001010100", - "policy_id": "01010101000001010000010001000001010001000100010101010001", + "asset_name": "0001000001000000010101010100010000000001010100000101000001010100", + "policy_id": "00010100000100010001000101000001010100010100000000000000", "quantity": 0 }, { - "asset_name": "0001000100010101010101000101000001000100010001000100000001010101", - "policy_id": "00010101000100010001000100000001000000000101000000010100", + "asset_name": "0001010001010000000000000101010101010101000100010101010001010000", + "policy_id": "01010100000000000001000100010101000000010101000000010101", "quantity": 1 } ] } }, - "message": "" - }, - { - "code": "asset_name_too_long", - "message": "\u0015\\K\u0005\u000c\u0005𐾰" + "message": "\u0019o\u001ex:鲙" }, { - "code": "shared_wallet_no_delegation_template", - "message": "{1TOW󺜁\u0018󸠂" - }, - { - "code": "balance_tx_existing_collateral", - "message": "R\u0019\u0000U-C괈m}I&A" - }, - { - "code": "balance_tx_existing_collateral", - "message": "^" + "code": "created_multidelegation_transaction", + "message": "𠝥\u0011[" }, { - "code": "tx_not_in_node_era", - "message": "\u001cHq$" + "code": "not_acceptable", + "message": "\\\u0019\u001cz" }, { - "code": "not_synced", - "message": "􃔢&[\u000b𓁈R 􈐘V@0読N" + "code": "unable_to_determine_current_epoch", + "message": "𛊐8" }, { - "code": "start_time_later_than_end_time", - "message": "" + "code": "output_token_bundle_size_exceeds_limit", + "message": "D\u0008I" }, { - "code": "not_found", - "message": "m_r\u0019!\u0007&𰝓" + "code": "created_wrong_policy_script_template", + "message": "𩰲􆹒犔􏵏%J􈮽\u0004g𦜢/" }, { - "code": "created_invalid_transaction", - "message": "\u0016𤞾k􀝗𠇥\u0019\u0002" + "code": "redeemer_invalid_data", + "message": "v4󶔙" } ], - "seed": -939439027 + "seed": -36971223 } \ No newline at end of file From e9cd7df9dade490d70f5ffaa3ddff7f52045a170 Mon Sep 17 00:00:00 2001 From: Pawel Jakubas Date: Wed, 15 May 2024 09:09:16 +0200 Subject: [PATCH 17/17] final code cleaning --- .../Test/Integration/Framework/TestData.hs | 98 ------------------- .../Scenario/API/Shared/Transactions.hs | 8 +- .../Scenario/API/Shelley/StakePools.hs | 28 +++--- .../Scenario/API/Shelley/Transactions.hs | 6 +- 4 files changed, 17 insertions(+), 123 deletions(-) diff --git a/lib/integration/framework/Test/Integration/Framework/TestData.hs b/lib/integration/framework/Test/Integration/Framework/TestData.hs index 8306d672986..9d3b4fad1a6 100644 --- a/lib/integration/framework/Test/Integration/Framework/TestData.hs +++ b/lib/integration/framework/Test/Integration/Framework/TestData.hs @@ -46,8 +46,6 @@ module Test.Integration.Framework.TestData -- * Error messages , errMsg400WalletIdEncoding , errMsg400StartTimeLaterThanEndTime - , errMsg403Fee - , errMsg403Collateral , errMsg403NotAByronWallet , errMsg403NotAnIcarusWallet , errMsg403WrongPass @@ -55,7 +53,6 @@ module Test.Integration.Framework.TestData , errMsg403AlreadyInLedger , errMsg403PoolAlreadyJoined , errMsg403NotDelegating - , errMsg403NonNullReward , errMsg403NothingToMigrate , errMsg404NoAsset , errMsg404NoEndpoint @@ -93,16 +90,6 @@ module Test.Integration.Framework.TestData , errMsg403TemplateInvalidUnknownCosigner , errMsg403TemplateInvalidDuplicateXPub , errMsg403TemplateInvalidScript - , errMsg403InvalidConstructTx - , errMsg403ForeignTransaction - , errMsg403MultidelegationTransaction - , errMsg403MultiaccountTransaction - , errMsg403CreatedWrongPolicyScriptTemplateTx - , errMsg403CreatedWrongPolicyScriptTemplatePolicyId - , errMsg403AssetNameTooLong - , errMsg403MintOrBurnAssetQuantityOutOfBounds - , errMsg403InvalidValidityBounds - , errMsg403ValidityIntervalNotInsideScriptTimelock ) where import Prelude @@ -325,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." - 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." @@ -348,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.\ @@ -444,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 @@ -623,69 +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." - ] - -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 -------------------------------------------------------------------------------- diff --git a/lib/integration/scenarios/Test/Integration/Scenario/API/Shared/Transactions.hs b/lib/integration/scenarios/Test/Integration/Scenario/API/Shared/Transactions.hs index bb0ccb1f521..507c036adf8 100644 --- a/lib/integration/scenarios/Test/Integration/Scenario/API/Shared/Transactions.hs +++ b/lib/integration/scenarios/Test/Integration/Scenario/API/Shared/Transactions.hs @@ -213,8 +213,6 @@ import Test.Integration.Framework.Request ) import Test.Integration.Framework.TestData ( errMsg400StartTimeLaterThanEndTime - , errMsg403Fee - , errMsg403InvalidConstructTx , errMsg404CannotFindTx , errMsg404NoWallet ) @@ -560,8 +558,8 @@ spec = describe "SHARED_TRANSACTIONS" $ do (Link.createUnsignedTransaction @'Shared wa) Default emptyPayload verify rTx [ expectResponseCode HTTP.status403 - , expectErrorMessage errMsg403InvalidConstructTx ] + decodeErrorInfo rTx `shouldBe` CreatedInvalidTransaction it "SHARED_TRANSACTIONS_CREATE_01b - \ \Validity interval only is not allowed" $ @@ -586,8 +584,8 @@ spec = describe "SHARED_TRANSACTIONS" $ do Default validityInterval verify rTx [ expectResponseCode HTTP.status403 - , expectErrorMessage errMsg403InvalidConstructTx ] + decodeErrorInfo rTx `shouldBe` CreatedInvalidTransaction it "SHARED_TRANSACTIONS_CREATE_04a - \ \Single Output Transaction with decode transaction - single party" $ @@ -843,8 +841,8 @@ spec = describe "SHARED_TRANSACTIONS" $ do (Link.createUnsignedTransaction @'Shared wa) Default payload verify rTx [ expectResponseCode HTTP.status403 - , expectErrorMessage errMsg403Fee ] + decodeErrorInfo rTx `shouldBe` CannotCoverFee it "SHARED_TRANSACTIONS_CREATE_04e - \ \Multiple Output Tx to single wallet" diff --git a/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/StakePools.hs b/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/StakePools.hs index 6301b0c8500..4c7c8fc5d08 100644 --- a/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/StakePools.hs +++ b/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/StakePools.hs @@ -53,7 +53,7 @@ import Cardano.Wallet.Api.Types.Amount ( ApiAmount (ApiAmount) ) import Cardano.Wallet.Api.Types.Error - ( ApiErrorInfo (NoSuchPool, NoUtxosAvailable, PoolAlreadyJoinedSameVote) + ( ApiErrorInfo (..) , ApiErrorNoSuchPool (..) ) import Cardano.Wallet.Faucet @@ -218,9 +218,7 @@ import Test.Integration.Framework.DSL , (.>=) ) import Test.Integration.Framework.TestData - ( errMsg403Fee - , errMsg403NotDelegating - , errMsg403PoolAlreadyJoined + ( errMsg403PoolAlreadyJoined , errMsg403WrongPass , errMsg404NoWallet ) @@ -754,12 +752,11 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do \Cannot quit when active: not_delegating" $ \ctx -> runResourceT $ do w <- fixtureWallet ctx - quitStakePool @n ctx (w, fixturePassphrase) - >>= flip - verify - [ expectResponseCode HTTP.status403 - , expectErrorMessage errMsg403NotDelegating - ] + rTx <- quitStakePool @n ctx (w, fixturePassphrase) + verify rTx + [ expectResponseCode HTTP.status403 + ] + decodeErrorInfo rTx `shouldBe` NotDelegatingTo it "STAKE_POOLS_QUIT_03 - Can quit with rewards" $ \ctx -> runResourceT $ do @@ -1169,12 +1166,11 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do ctx (Link.listStakePools arbitraryStake) Empty - joinStakePool @n ctx (SpecificPool pool) (w, fixturePassphrase) - >>= flip - verify - [ expectResponseCode HTTP.status403 - , expectErrorMessage errMsg403Fee - ] + rTx <- joinStakePool @n ctx (SpecificPool pool) (w, fixturePassphrase) + verify rTx + [ expectResponseCode HTTP.status403 + ] + decodeErrorInfo rTx `shouldBe` CannotCoverFee describe "STAKE_POOLS_QUIT_01x - Fee boundary values" $ do it diff --git a/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/Transactions.hs b/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/Transactions.hs index 5c27f20cc2b..1f42b6f85bb 100644 --- a/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/Transactions.hs +++ b/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/Transactions.hs @@ -217,7 +217,6 @@ import Test.Integration.Framework.TestData ( errMsg400StartTimeLaterThanEndTime , errMsg400TxMetadataStringTooLong , errMsg403AlreadyInLedger - , errMsg403Fee , errMsg403WithdrawalNotBeneficial , errMsg403WrongPass , errMsg404CannotFindTx @@ -765,11 +764,10 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do (Link.createTransactionOld @'Shelley wSrc) Default payload - verify - r + verify r [ expectResponseCode HTTP.status403 - , expectErrorMessage errMsg403Fee ] + decodeErrorInfo r `shouldBe` CannotCoverFee it "TRANS_CREATE_04 - Not enough money" $ \ctx -> runResourceT $ do let minUTxOValue' = minUTxOValue (_mainEra ctx)