# blockfrost-client
Haskell SDK for [Blockfrost.io](https://blockfrost.io) API.
## Development shell
```sh
nix-shell # from repository root, optional
cabal repl blockfrost-client
```
## Usage
[Blockfrost.io](https://blockfrost.io) API token is required to use this SDK.
### Obtaining token
Create a project at [blockfrost.io](https://blockfrost.io) and save the
generated token to a file.
For authentication, client uses a `Project` type which carries an environment and a token itself, for example `Project Testnet "someToken"`.
#### Project from file
Instead of constructing this type manually, you can load the `Project`
from file using `projectFromFile "/secrets/blockfrost-testnet-token"`.
In this case, token needs to be prefixed with the enviromnent to which
it belongs to. The format expected is `<env><token>` (similar to human readable
identifiers used for Cardano keys and addresses), examples:
* `testnet123notArealToken`
* `mainnet456notRealEither`
* `ipfs789mightBeARealOne`
### Using environment variables
In similar manner to loading project from file, you can use
`projectFromEnv` function to load the `Project` from file
pointed to by `BLOCKFROST_TOKEN_PATH` environment variable.
For custom variable name, a principled version `projectFromEnv' "CUSTOM_ENV_VAR"` can be used instead.
## Exploring the API
You can now perform queries from `cabal repl blockfrost-client`, an example session follows:
```haskell
λ: testnet <- projectFromFile "/secrets/blockfrost.testnet.token"
λ: testnet
Project {projectEnv = Testnet, projectId = "censored"}
λ: runBlockfrost testnet $ getLatestBlock
Right (Block {_blockTime = 1629716610s, ... })
λ: runBlockfrost testnet $ listPools
Right [PoolId "pool1adur9jcn0dkjpm3v8ayf94yn3fe5xfk2rqfz7rfpuh6cw6evd7w", ... ]
```
## Pagination and sorting
Some API functions have a variant with trailing `'`. These accept
`Paged` and `SortOrder` arguments for querying multiple pages
and setting a custom sort order.
For example to query the second page of pool list, we can use `listPools'`
```haskell
λ: runBlockfrost testnet $ listPools' (page 2) desc
```
To use default ordering (which is `asc` or `Ascending`), you can just use re-exported `def` from [Data.Default](https://hackage.haskell.org/package/data-default/docs/Data-Default.html).
```haskell
λ: runBlockfrost testnet $ listPools' (page 2) def
```
Similar, to just change an ordering but use default page size and a first page:
```haskell
λ: runBlockfrost testnet $ listPools' def desc
```
## Catching errors
We can use `tryError` inside `BlockfrostClient` monad to try a call,
when we it may fail (dealing with external inputs, enumerating addresses).
Complete program example with error handling:
```haskell
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Main
where
import Blockfrost.Client
main = do
-- reads token from BLOCKFROST_TOKEN_PATH
-- environment variable. It expects token
-- prefixed with Blockfrost environment name
-- e.g.: testnet-someTokenHash
prj <- projectFromEnv
res <- runBlockfrost prj $ do
latestBlocks <- getLatestBlock
(ers :: Either BlockfrostError [AccountReward]) <-
tryError $ getAccountRewards "gonnaFail"
pure (latestBlocks, ers)
print res
```