Skip to content

Commit

Permalink
Api schema skeleton and the testing infra (#4727)
Browse files Browse the repository at this point in the history
<!--
Detail in a few bullet points the work accomplished in this PR.

Before you submit, don't forget to:

* Make sure the GitHub PR fields are correct:
   ✓ Set a good Title for your PR.
   ✓ Assign yourself to the PR.
   ✓ Assign one or more reviewer(s).
   ✓ Link to a Jira issue, and/or other GitHub issues or PRs.
   ✓ In the PR description delete any empty sections
     and all text commented in <!--, so that this text does not appear
     in merge commit messages.

* Don't waste reviewers' time:
   ✓ If it's a draft, select the Create Draft PR option.
✓ Self-review your changes to make sure nothing unexpected slipped
through.

* Try to make your intent clear:
   ✓ Write a good Description that explains what this PR is meant to do.
   ✓ Jira will detect and link to this PR once created, but you can also
     link this PR in the description of the corresponding Jira ticket.
   ✓ Highlight what Testing you have done.
   ✓ Acknowledge any changes required to the Documentation.
-->

- [x] Added endpoint paths
- [x] Added input/output types schemas
- [x] clean old yaml approach
- [x] added schema checks
- [x] swagger.yaml generation and checking

### Comments

<!-- Additional comments, links, or screenshots to attach, if any. -->

### Issue Number

<!-- Reference the Jira/GitHub issue that this PR relates to, and which
requirements it tackles.
  Note: Jira issues of the form ADP- will be auto-linked. -->
  • Loading branch information
paweljakubas authored Aug 14, 2024
2 parents 326d39c + 443681b commit 52f7d49
Show file tree
Hide file tree
Showing 10 changed files with 461 additions and 119 deletions.
14 changes: 14 additions & 0 deletions lib/customer-deposit-wallet/customer-deposit-wallet.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ author: Cardano Foundation (High Assurance Lab)
maintainer: hal@cardanofoundation.org
copyright: 2023 Cardano Foundation
category: Web
data-files: data/swagger.json

extra-source-files:
spec/**/*.lagda.md
Expand Down Expand Up @@ -109,9 +110,15 @@ library customer-deposit-wallet-http
hs-source-dirs: http
build-depends:
, aeson
, aeson-pretty
, base
, bytestring
, customer-deposit-wallet
, http-media
, insert-ordered-containers
, lens
, memory
, openapi3
, servant
, servant-server
, text
Expand All @@ -124,6 +131,7 @@ library customer-deposit-wallet-http
Cardano.Wallet.Deposit.HTTP.Types.API
Cardano.Wallet.Deposit.HTTP.Types.JSON
Cardano.Wallet.Deposit.HTTP.Types.JSON.Encoding
Cardano.Wallet.Deposit.HTTP.Types.OpenAPI

test-suite unit
import: language, opts-exe
Expand All @@ -132,20 +140,26 @@ test-suite unit
main-is: test-suite-unit.hs
build-depends:
, aeson
, aeson-pretty
, base
, bytestring
, cardano-crypto
, cardano-wallet:cardano-wallet
, cardano-wallet-primitive
, cardano-wallet-test-utils
, customer-deposit-wallet:{customer-deposit-wallet, customer-deposit-wallet-http}
, directory
, hspec >=2.8.2
, hspec-golden
, openapi3
, QuickCheck
, with-utf8
build-tool-depends: hspec-discover:hspec-discover
other-modules:
Cardano.Wallet.Deposit.HTTP.JSON.JSONSpec
Cardano.Wallet.Deposit.HTTP.OpenAPISpec
Cardano.Wallet.Deposit.PureSpec
Paths_customer_deposit_wallet
Spec

executable customer-deposit-wallet
Expand Down
70 changes: 70 additions & 0 deletions lib/customer-deposit-wallet/data/swagger.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"components": {
"schemas": {
"ApiT Address": {
"format": "hex",
"type": "string"
},
"ApiT Customer": {
"maximum": 2147483647,
"minimum": 0,
"type": "integer"
},
"ApiT CustomerList": {
"items": {
"properties": {
"address": {
"format": "hex",
"type": "string"
},
"customer": {
"maximum": 2147483647,
"minimum": 0,
"type": "integer"
}
},
"type": "object"
},
"type": "array"
}
}
},
"info": {
"description": "This is the API for the deposit wallet",
"license": {
"name": "Apache 2",
"url": "https://www.apache.org/licenses/LICENSE-2.0.html"
},
"title": "Cardano Deposit Wallet API",
"version": "0.0.0.1"
},
"openapi": "3.0.0",
"paths": {
"/customers": {
"parameters": [
{
"in": "path",
"name": "customerId",
"schema": {
"$ref": "#/components/schemas/ApiT Customer"
}
}
],
"put": {
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ApiT Address"
}
}
},
"description": "Ok"
}
},
"summary": "Add customer"
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ module Cardano.Wallet.Deposit.HTTP.Implementation
where

import Cardano.Wallet.Deposit.HTTP.Types.API
( API
( CustomerAPI
)
import Data.Proxy
( Proxy (..)
Expand All @@ -29,10 +29,10 @@ import qualified Cardano.Wallet.Deposit.IO as Wallet
{-----------------------------------------------------------------------------
Types
------------------------------------------------------------------------------}
api :: Proxy API
api :: Proxy CustomerAPI
api = Proxy

implementation :: Wallet.WalletInstance -> Server API
implementation :: Wallet.WalletInstance -> Server CustomerAPI
implementation w =
HTTP.listCustomers w
:<|> HTTP.createAddress w
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
-- Servant Type for our HTTP API.
--
module Cardano.Wallet.Deposit.HTTP.Types.API
( API
( CustomerAPI
)
where

Expand All @@ -30,7 +30,7 @@ import Servant.API
API
------------------------------------------------------------------------------}

type API =
type CustomerAPI =
"customers"
:> Verb 'GET 200 '[JSON] (ApiT CustomerList)
:<|>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ import Prelude

import Cardano.Wallet.Deposit.HTTP.Types.JSON.Encoding
( ViaText (..)
, customOptions
)
import Cardano.Wallet.Deposit.HTTP.Types.OpenAPI
( addressSchema
, customerListSchema
, customerSchema
)
import Cardano.Wallet.Deposit.Pure
( Customer
Expand All @@ -33,12 +37,20 @@ import Cardano.Wallet.Deposit.Read
import Data.Aeson
( FromJSON (..)
, ToJSON (..)
, genericParseJSON
, genericToJSON
, object
, withObject
, (.:)
, (.=)
)
import Data.Aeson.Types
( Parser
)
import Data.Bifunctor
( bimap
, first
( first
)
import Data.OpenApi
( NamedSchema (..)
, ToSchema (..)
)
import Data.Text
( Text
Expand Down Expand Up @@ -74,6 +86,13 @@ newtype ApiT a = ApiT {unApiT :: a}
deriving via ViaText Address instance FromJSON (ApiT Address)
deriving via ViaText Address instance ToJSON (ApiT Address)

instance ToSchema (ApiT Address) where
declareNamedSchema _ = do
pure
$ NamedSchema
(Just "ApiT Address")
addressSchema

-- Customer
instance FromHttpApiData (ApiT Customer) where
parseUrlPiece = fmap (ApiT . toEnum) . fromText'
Expand All @@ -84,21 +103,40 @@ instance FromJSON (ApiT Customer) where
instance ToJSON (ApiT Customer) where
toJSON = toJSON . fromEnum . unApiT

instance ToSchema (ApiT Customer) where
declareNamedSchema _ = do
pure
$ NamedSchema
(Just "ApiT Customer")
customerSchema

-- | 'fromText' but with a simpler error type.
fromText' :: FromText a => Text -> Either Text a
fromText' = first (T.pack . getTextDecodingError) . fromText

-- CustomerList
type ApiCustomerList = [(ApiT Customer, ApiT Address)]

toApiCustomerList :: ApiT CustomerList -> ApiCustomerList
toApiCustomerList = fmap (bimap ApiT ApiT) . unApiT
instance ToJSON (ApiT (Customer, Address)) where
toJSON (ApiT (c, a)) = object
[ "customer" .= toJSON (ApiT c)
, "address" .= toJSON (ApiT a)
]

fromApiCustomerList :: ApiCustomerList -> ApiT CustomerList
fromApiCustomerList = ApiT . fmap (bimap unApiT unApiT)
instance FromJSON (ApiT (Customer, Address)) where
parseJSON = withObject "ApiT (Customer, Address)" $ \obj -> do
customerApiT <- obj .: "customer"
addressApiT <- obj .: "address"
pure $ ApiT (unApiT customerApiT, unApiT addressApiT)

instance FromJSON (ApiT CustomerList) where
parseJSON = fmap fromApiCustomerList . genericParseJSON customOptions
parseJSON l = do
custoList <- (parseJSON l :: Parser [ApiT (Customer, Address)])
pure $ ApiT (unApiT <$> custoList)

instance ToJSON (ApiT CustomerList) where
toJSON = genericToJSON customOptions . toApiCustomerList
toJSON (ApiT cl)= toJSON (toJSON . ApiT <$> cl)

instance ToSchema (ApiT CustomerList) where
declareNamedSchema _ = do
pure
$ NamedSchema
(Just "ApiT CustomerList")
customerListSchema
Loading

0 comments on commit 52f7d49

Please sign in to comment.