Skip to content

Commit

Permalink
Make error message more useful on failure to parse ApiAsArray.
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathanknowles committed Apr 27, 2022
1 parent 2ad4a1d commit 2fc0a28
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 44 deletions.
22 changes: 14 additions & 8 deletions lib/core/src/Cardano/Wallet/Api/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ import Fmt
import GHC.Generics
( Generic, Rep )
import GHC.TypeLits
( Nat, Symbol )
( KnownSymbol, Nat, Symbol, symbolVal )
import Numeric.Natural
( Natural )
import Quiet
Expand Down Expand Up @@ -1146,8 +1146,9 @@ data ApiTransaction (n :: NetworkDiscriminant) = ApiTransaction
, inputs :: ![ApiTxInput n]
, outputs :: ![AddressAmount (ApiT Address, Proxy n)]
, collateral :: ![ApiTxCollateral n]
, collateralOutputs
:: !(ApiAsArray (Maybe (AddressAmount (ApiT Address, Proxy n))))
, collateralOutputs ::
!(ApiAsArray "collateral_outputs"
(Maybe (AddressAmount (ApiT Address, Proxy n))))
, withdrawals :: ![ApiWithdrawal n]
, mint :: !(ApiT W.TokenMap)
, status :: !(ApiT TxStatus)
Expand Down Expand Up @@ -1275,7 +1276,8 @@ data ApiDecodedTransaction (n :: NetworkDiscriminant) = ApiDecodedTransaction
, inputs :: ![ApiTxInputGeneral n]
, outputs :: ![ApiTxOutputGeneral n]
, collateral :: ![ApiTxInputGeneral n]
, collateralOutputs :: !(ApiAsArray (Maybe (ApiTxOutputGeneral n)))
, collateralOutputs ::
!(ApiAsArray "collateral_outputs" (Maybe (ApiTxOutputGeneral n)))
, withdrawals :: ![ApiWithdrawalGeneral n]
, mint :: !ApiAssetMintBurn
, burn :: !ApiAssetMintBurn
Expand Down Expand Up @@ -4144,19 +4146,23 @@ instance ToJSON (ApiT TxScriptValidity) where
--
-- The number of items permitted in the array is dependent on the wrapped type.
--
newtype ApiAsArray a = ApiAsArray a
newtype ApiAsArray (s :: Symbol) a = ApiAsArray a
deriving (Eq, Generic, Show, Typeable)
deriving newtype (Monoid, Semigroup)
deriving anyclass NFData

instance FromJSON a => FromJSON (ApiAsArray (Maybe a)) where
instance (KnownSymbol s, FromJSON a) => FromJSON (ApiAsArray s (Maybe a)) where
parseJSON json = parseJSON @[a] json >>= \case
[a] ->
pure $ ApiAsArray $ Just a
[] ->
pure $ ApiAsArray Nothing
_ ->
fail "Expected at most one item."
fail $ mconcat
[ "Expected at most one item for "
, show $ symbolVal $ Proxy @s
, "."
]

instance ToJSON a => ToJSON (ApiAsArray (Maybe a)) where
instance ToJSON a => ToJSON (ApiAsArray s (Maybe a)) where
toJSON (ApiAsArray m) = toJSON (maybeToList m)
31 changes: 0 additions & 31 deletions lib/core/test/data/Cardano/Wallet/Api/ApiAsArrayMaybeWord64.json

This file was deleted.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 7 additions & 5 deletions lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ spec = parallel $ do
describe "JSON golden roundtrip" $ do
jsonTest @(AddressAmount (ApiT Address, Proxy ('Testnet 0)))
jsonTest @(AddressAmountNoAssets (ApiT Address, Proxy ('Testnet 0)))
jsonTest @(ApiAsArray (Maybe Word64))
jsonTest @(ApiAsArray "Test" (Maybe Word64))
jsonTest @(ApiBalanceTransactionPostData ('Testnet 0))
jsonTest @(ApiCoinSelection ('Testnet 0))
jsonTest @(ApiCoinSelectionChange ('Testnet 0))
Expand Down Expand Up @@ -662,7 +662,9 @@ spec = parallel $ do

describe "ApiAsArray (Maybe t)" $ do
let parseApiAsArray = Aeson.parseEither $
parseJSON @(ApiAsArray (Maybe Word64))
parseJSON @(ApiAsArray "test_field" (Maybe Word64))
let expectedFailureMessage =
"Error in $: Expected at most one item for \"test_field\"."
it "element count = 0 (should succeed)" $
parseApiAsArray [aesonQQ|[]|]
`shouldBe` Right (ApiAsArray Nothing)
Expand All @@ -671,10 +673,10 @@ spec = parallel $ do
`shouldBe` Right (ApiAsArray (Just 0))
it "element count = 2 (should fail)" $
parseApiAsArray [aesonQQ|[0, 1]|]
`shouldBe` Left "Error in $: Expected at most one item."
`shouldBe` Left expectedFailureMessage
it "element count = 3 (should fail)" $
parseApiAsArray [aesonQQ|[0, 1, 2]|]
`shouldBe` Left "Error in $: Expected at most one item."
`shouldBe` Left expectedFailureMessage

it "ApiT (Passphrase \"user\") (too short)" $ do
let minLength = passphraseMinLength (Proxy :: Proxy "user")
Expand Down Expand Up @@ -2470,7 +2472,7 @@ selectFromPreparedBinaries = elements $ toByteString <$>
genWits :: Gen ByteString
genWits = BS.pack <$> Test.QuickCheck.scale (min 32) (listOf arbitrary)

deriving instance Arbitrary a => Arbitrary (ApiAsArray a)
deriving instance Arbitrary a => Arbitrary (ApiAsArray s a)

instance Arbitrary (ApiBytesT base ByteString) where
arbitrary = ApiBytesT <$> selectFromPreparedBinaries
Expand Down

0 comments on commit 2fc0a28

Please sign in to comment.