Skip to content
This repository was archived by the owner on Aug 18, 2020. It is now read-only.

Commit 12131d9

Browse files
akegaljKtorZ
authored andcommitted
Akegalj/co 319/swagger account index (#3086)
* [CO-319] Fix account index swagger example * [CO-319] Add roundtrip tests * [CO-319] Fix recursive buildable instances * [CO-319] Use strongly typed error * [CO-319] Remove duplication in 'renderAccountIndexError' * [CO-319] Distangle V1/Errors This makes it now possible to import V1/Errors from the V1/Types module and leverage errors from this module. One thing is still unclear to me: Why Errors isn't defined in V1/Types already? There's a circular dependency between V1/Response and V1/Types if we go this way, as well as between V1/Migration and V1/Types. Nevertheless, it would make sense to have three data-types here: - WalletError (defined in V1/Types) - MigrationError (defined in V1/Types) - JSONParsingError (defined in Response) This way, we could remove the conflicting constructor from WalletError and remove the need for an extra module here. It will also makes thing clearer * [CO-319] Make V1/Error part of V1/Types To realize this, we had to extract JSONValidationFailed and MigrationFailed constructor from WalletError. They're now defined as constructor in different data-types (resp. JSONValidationError and MigrationError). * [CO-319] Solve rebase conflicts * [CO-319] Correctly format (jsend) newtype errors This is rather ugly and could probably be achieved nicely with a better understanding of the Generics.SOP library. As far as I could tell, there's no easy way to retrieve 'Tag' for single constructor (cf: 'For a datatype with a single constructor we do not need to tag values with their constructor; but for a datatype with multiple constructors we do. ')
1 parent 85ed9be commit 12131d9

File tree

16 files changed

+603
-386
lines changed

16 files changed

+603
-386
lines changed

wallet-new/cardano-sl-wallet-new.cabal

+2-1
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,10 @@ library
3939
Cardano.Wallet.API.V1
4040
Cardano.Wallet.API.V1.Accounts
4141
Cardano.Wallet.API.V1.Addresses
42-
Cardano.Wallet.API.V1.Errors
4342
Cardano.Wallet.API.V1.Generic
43+
Cardano.Wallet.API.V1.Errors
4444
Cardano.Wallet.API.V1.Handlers
45+
Cardano.Wallet.API.V1.Headers
4546
Cardano.Wallet.API.V1.Info
4647
Cardano.Wallet.API.V1.LegacyHandlers
4748
Cardano.Wallet.API.V1.LegacyHandlers.Accounts

wallet-new/integration/TransactionSpecs.hs

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ module TransactionSpecs (transactionSpecs) where
55

66
import Universum hiding (log)
77

8-
import Cardano.Wallet.API.V1.Errors hiding (describe)
98
import Cardano.Wallet.Client.Http
9+
import Control.Concurrent (threadDelay)
1010
import Control.Lens
11-
import qualified Pos.Core as Core
1211
import Test.Hspec
13-
14-
import Control.Concurrent (threadDelay)
1512
import Text.Show.Pretty (ppShow)
13+
14+
import qualified Pos.Core as Core
15+
1616
import Util
1717

1818
{-# ANN module ("HLint: ignore Reduce duplication" :: Text) #-}

wallet-new/src/Cardano/Wallet/API/Response.hs

+56-16
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
{-# LANGUAGE DeriveFunctor #-}
22
{-# LANGUAGE DeriveGeneric #-}
3+
{-# LANGUAGE LambdaCase #-}
34
{-# LANGUAGE OverloadedLists #-}
45
module Cardano.Wallet.API.Response (
56
Metadata (..)
67
, ResponseStatus(..)
78
, WalletResponse(..)
9+
, JSONValidationError(..)
810
-- * Generating responses for collections
911
, respondWith
1012
-- * Generating responses for single resources
@@ -13,35 +15,39 @@ module Cardano.Wallet.API.Response (
1315
) where
1416

1517
import Prelude
16-
import Universum (Buildable, decodeUtf8, toText, (<>))
18+
import Universum (Buildable, Exception, Text, decodeUtf8, toText,
19+
(<>))
1720

21+
import Cardano.Wallet.API.Indices (Indexable', IxSet')
22+
import Cardano.Wallet.API.Request (RequestParams (..))
23+
import Cardano.Wallet.API.Request.Filter (FilterOperations (..))
24+
import Cardano.Wallet.API.Request.Pagination (Page (..),
25+
PaginationMetadata (..), PaginationParams (..),
26+
PerPage (..))
27+
import Cardano.Wallet.API.Request.Sort (SortOperations (..))
28+
import Cardano.Wallet.API.Response.Filter.IxSet as FilterBackend
1829
import Cardano.Wallet.API.Response.JSend (ResponseStatus (..))
30+
import Cardano.Wallet.API.Response.Sort.IxSet as SortBackend
31+
import Cardano.Wallet.API.V1.Errors (ToServantError (..))
32+
import Cardano.Wallet.API.V1.Generic (gparseJsend, gtoJsend)
1933
import Control.Lens
2034
import Data.Aeson
2135
import Data.Aeson.Encode.Pretty (encodePretty)
2236
import Data.Aeson.TH
23-
import qualified Data.Char as Char
2437
import Data.Swagger as S
25-
import qualified Data.Text.Buildable
2638
import Data.Typeable
2739
import Formatting (bprint, build, (%))
40+
import Generics.SOP.TH (deriveGeneric)
2841
import GHC.Generics (Generic)
29-
import qualified Serokell.Aeson.Options as Serokell
42+
import Servant (err400)
3043
import Servant.API.ContentTypes (Accept (..), JSON, MimeRender (..),
3144
MimeUnrender (..), OctetStream)
3245
import Test.QuickCheck
3346

34-
import Cardano.Wallet.API.Indices (Indexable', IxSet')
35-
import Cardano.Wallet.API.Request (RequestParams (..))
36-
import Cardano.Wallet.API.Request.Filter (FilterOperations (..))
37-
import Cardano.Wallet.API.Request.Pagination (Page (..),
38-
PaginationMetadata (..), PaginationParams (..),
39-
PerPage (..))
40-
import Cardano.Wallet.API.Request.Sort (SortOperations (..))
41-
import Cardano.Wallet.API.Response.Filter.IxSet as FilterBackend
42-
import Cardano.Wallet.API.Response.Sort.IxSet as SortBackend
43-
import Cardano.Wallet.API.V1.Errors
44-
(WalletError (JSONValidationFailed))
47+
import qualified Data.Char as Char
48+
import qualified Data.Text.Buildable
49+
import qualified Serokell.Aeson.Options as Serokell
50+
4551

4652
-- | Extra information associated with an HTTP response.
4753
data Metadata = Metadata
@@ -138,7 +144,7 @@ respondWith :: (Monad m, Indexable' a)
138144
-> m (WalletResponse [a])
139145
respondWith RequestParams{..} fops sorts generator = do
140146
(theData, paginationMetadata) <- paginate rpPaginationParams . sortData sorts . applyFilters fops <$> generator
141-
return $ WalletResponse {
147+
return WalletResponse {
142148
wrData = theData
143149
, wrStatus = SuccessStatus
144150
, wrMeta = Metadata paginationMetadata
@@ -184,3 +190,37 @@ instance Accept ValidJSON where
184190

185191
instance ToJSON a => MimeRender ValidJSON a where
186192
mimeRender _ = mimeRender (Proxy @ JSON)
193+
194+
195+
--
196+
-- Error from parsing / validating JSON inputs
197+
--
198+
199+
newtype JSONValidationError
200+
= JSONValidationFailed Text
201+
deriving (Show, Eq)
202+
203+
deriveGeneric ''JSONValidationError
204+
205+
instance ToJSON JSONValidationError where
206+
toJSON = gtoJsend ErrorStatus
207+
208+
instance FromJSON JSONValidationError where
209+
parseJSON = gparseJsend
210+
211+
instance Exception JSONValidationError
212+
213+
instance Arbitrary JSONValidationError where
214+
arbitrary = oneof
215+
[ pure $ JSONValidationFailed "JSON validation failed."
216+
]
217+
218+
instance Buildable JSONValidationError where
219+
build = \case
220+
JSONValidationFailed _ ->
221+
bprint "Couldn't decode a JSON input."
222+
223+
instance ToServantError JSONValidationError where
224+
declareServantError = \case
225+
JSONValidationFailed _ ->
226+
err400

0 commit comments

Comments
 (0)