-
Notifications
You must be signed in to change notification settings - Fork 213
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a simple API client for the Cardano HTTP Bridge.
- Loading branch information
1 parent
e1d074d
commit 6c0935f
Showing
9 changed files
with
280 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
{-# LANGUAGE DataKinds #-} | ||
{-# LANGUAGE TypeOperators #-} | ||
|
||
-- | An API specification for the Cardano HTTP Bridge. | ||
module Cardano.ChainProducer.RustHttpBridge.Api | ||
( Api | ||
, api | ||
, Block (..) | ||
, BlockHeader (..) | ||
, EpochId (..) | ||
, NetworkName (..) | ||
) where | ||
|
||
import Cardano.Wallet.Binary | ||
( decodeBlock, decodeBlockHeader ) | ||
import Codec.CBOR.Extra | ||
( FromCBOR (fromCBOR) ) | ||
import Crypto.Hash.Algorithms | ||
( Blake2b_256 ) | ||
import Data.Text | ||
( Text ) | ||
import Prelude | ||
import Servant | ||
( Proxy (..) ) | ||
import Servant.API | ||
( (:<|>), (:>), Capture, Get, ToHttpApiData (..) ) | ||
import Servant.Extra.ContentTypes | ||
( CBOR, ComputeHash, Hash, Packed, WithHash ) | ||
|
||
import qualified Cardano.Wallet.Primitive as Primitive | ||
|
||
api :: Proxy Api | ||
api = Proxy | ||
|
||
type Api | ||
= GetBlockByHash | ||
:<|> GetEpochById | ||
:<|> GetTipBlockHeader | ||
|
||
-- | Retrieve a block identified by the unique hash of its header. | ||
type GetBlockByHash | ||
= Capture "networkName" NetworkName | ||
:> "block" | ||
:> Capture "blockHeaderHash" (Hash Blake2b_256 BlockHeader) | ||
:> Get '[CBOR] Block | ||
|
||
-- | Retrieve all the blocks for the epoch identified by the given integer ID. | ||
type GetEpochById | ||
= Capture "networkName" NetworkName | ||
:> "epoch" | ||
:> Capture "epochId" EpochId | ||
:> Get '[Packed CBOR] [Block] | ||
|
||
-- | Retrieve the header of the latest known block. | ||
type GetTipBlockHeader | ||
= Capture "networkName" NetworkName | ||
:> "tip" | ||
:> Get '[ComputeHash Blake2b_256 CBOR] (WithHash Blake2b_256 BlockHeader) | ||
|
||
-- | Represents a block. | ||
-- | ||
newtype Block = Block | ||
{ getBlock :: Primitive.Block | ||
} deriving Eq | ||
|
||
instance FromCBOR Block where | ||
fromCBOR = Block <$> decodeBlock | ||
|
||
-- | Represents a block header. | ||
-- | ||
newtype BlockHeader = BlockHeader | ||
{ getBlockHeader :: Primitive.BlockHeader | ||
} deriving Eq | ||
|
||
instance FromCBOR BlockHeader where | ||
fromCBOR = BlockHeader <$> decodeBlockHeader | ||
|
||
-- | Represents a unique epoch. | ||
-- | ||
newtype EpochId = EpochId | ||
{ getEpochId :: Primitive.EpochId | ||
} deriving (Eq, Show) | ||
|
||
instance ToHttpApiData (EpochId) where | ||
toUrlPiece = toUrlPiece . Primitive.getEpochId . getEpochId | ||
|
||
-- | Represents the name of a Cardano network. | ||
-- | ||
newtype NetworkName = NetworkName | ||
{ getNetworkName :: Text | ||
} deriving (Eq, Show) | ||
|
||
instance ToHttpApiData NetworkName where | ||
toUrlPiece = getNetworkName | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
{-# LANGUAGE DataKinds #-} | ||
{-# LANGUAGE FlexibleInstances #-} | ||
{-# LANGUAGE RankNTypes #-} | ||
|
||
-- | An API client for the Cardano HTTP Bridge. | ||
module Cardano.ChainProducer.RustHttpBridge.Client | ||
( getBlockByHash | ||
, getEpochById | ||
, getTipBlockHeader | ||
) where | ||
|
||
import Cardano.ChainProducer.RustHttpBridge.Api | ||
( Block, BlockHeader, EpochId, NetworkName, api ) | ||
import Crypto.Hash.Algorithms | ||
( Blake2b_256 ) | ||
import Servant.API | ||
( (:<|>) (..) ) | ||
import Servant.Client | ||
( ClientM, client ) | ||
import Servant.Extra.ContentTypes | ||
( Hash, WithHash ) | ||
|
||
-- | Retrieve a block identified by the unique hash of its header. | ||
getBlockByHash :: NetworkName -> Hash Blake2b_256 BlockHeader -> ClientM Block | ||
|
||
-- | Retrieve all the blocks for the epoch identified by the given integer ID. | ||
getEpochById :: NetworkName -> EpochId -> ClientM [Block] | ||
|
||
-- | Retrieve the header of the latest known block. | ||
getTipBlockHeader :: NetworkName -> ClientM (WithHash Blake2b_256 BlockHeader) | ||
|
||
getBlockByHash | ||
:<|> getEpochById | ||
:<|> getTipBlockHeader | ||
= client api | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
-- | Useful extra functions related to CBOR processing. | ||
-- | ||
module Codec.CBOR.Extra | ||
( FromCBOR (..) | ||
) where | ||
|
||
import qualified Codec.CBOR.Decoding as CBOR | ||
|
||
-- | The class of types that can be converted to from CBOR. | ||
-- | ||
class FromCBOR a where | ||
fromCBOR :: CBOR.Decoder s a | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
{-# LANGUAGE DataKinds #-} | ||
{-# LANGUAGE FlexibleInstances #-} | ||
{-# LANGUAGE MultiParamTypeClasses #-} | ||
{-# LANGUAGE ScopedTypeVariables #-} | ||
|
||
-- | Extra content types for Servant. | ||
-- | ||
module Servant.Extra.ContentTypes | ||
( ComputeHash | ||
, CBOR | ||
, Hash (..) | ||
, Packed | ||
, WithHash (..) | ||
) where | ||
|
||
import Cardano.Wallet.Binary.Packfile | ||
( decodePackfile ) | ||
import Codec.CBOR.Extra | ||
( FromCBOR (..) ) | ||
import Crypto.Hash | ||
( Digest, hashWith ) | ||
import Crypto.Hash.IO | ||
( HashAlgorithm (..) ) | ||
import Data.Proxy | ||
( Proxy (..) ) | ||
import Data.Text.Encoding | ||
( decodeUtf8 ) | ||
import Network.HTTP.Media | ||
( (//) ) | ||
import Prelude | ||
import Servant.API | ||
( Accept (..), MimeUnrender (..), ToHttpApiData (..) ) | ||
|
||
import qualified Codec.CBOR.Read as CBOR | ||
import qualified Data.ByteArray as BA | ||
import qualified Data.ByteString.Lazy as BL | ||
|
||
-- | Represents a CBOR (Concise Binary Object Representation) object. | ||
-- | ||
-- See RFC 7049 (http://cbor.io/) for further details. | ||
-- | ||
data CBOR | ||
|
||
instance Accept CBOR where | ||
contentType _ = "application" // "cbor" | ||
|
||
instance FromCBOR a => MimeUnrender CBOR a where | ||
mimeUnrender _ bl = either | ||
(Left . show) | ||
(Right . snd) | ||
(CBOR.deserialiseFromBytes fromCBOR bl) | ||
|
||
-- | Represents a piece of binary data for which a hash value should be | ||
-- calculated before performing any further deserialization. | ||
-- | ||
data ComputeHash algorithm a | ||
|
||
-- | Represents the result of hashing a piece of data. | ||
-- | ||
newtype Hash algorithm a = Hash (Digest algorithm) | ||
|
||
instance ToHttpApiData (Hash algorithm a) where | ||
toUrlPiece (Hash digest) = decodeUtf8 $ BA.convert digest | ||
|
||
-- | Represents a piece of data with an accompanying hash value. | ||
data WithHash algorithm a = WithHash | ||
{ getHash :: Digest algorithm | ||
, getValue :: a | ||
} deriving Show | ||
|
||
instance Accept a => Accept (ComputeHash algorithm a) where | ||
contentType _ = contentType (Proxy :: Proxy a) | ||
|
||
instance forall a b alg . (MimeUnrender a b, HashAlgorithm alg) => | ||
MimeUnrender (ComputeHash alg a) (WithHash alg b) where | ||
mimeUnrender _ bl = | ||
WithHash (hashWith (undefined :: alg) $ BL.toStrict bl) | ||
<$> mimeUnrender (Proxy :: Proxy a) bl | ||
|
||
-- | Represents something that has been packed with the Cardano packfile format. | ||
-- | ||
data Packed a | ||
|
||
instance Accept a => Accept (Packed a) where | ||
contentType _ = "application" // "cardano-pack" | ||
|
||
instance forall a b . MimeUnrender a b => MimeUnrender (Packed a) [b] where | ||
mimeUnrender _ bs = either | ||
(Left . show) | ||
(traverse $ mimeUnrender (Proxy :: Proxy a) . BL.fromStrict) | ||
(decodePackfile bs) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters