plaid-0.1.0.0: examples/Main.hs
module Main where
{-
Module containing useful real world examples of using plaid library.
-}
import Control.Exception.Safe (MonadThrow, throwM)
import Control.Monad.Except (liftEither, runExceptT)
import Control.Monad.Reader
import Data.ByteString.Lazy (ByteString)
import Data.Plaid
import Data.Text (Text)
import Data.Time
import Text.Pretty.Simple
-- | Client id
clientId :: ClientId
clientId = ClientId "5d11dd0fdeb8a80013cc99e9"
-- | Public key
publicKey :: PublicKey
publicKey = "f19293a734d8e9cc89faacb09719e5"
-- | Sandbox secret key
sandboxSecret :: Secret
sandboxSecret = Secret "0d5e0ec25d432388f7fb34d3528394"
-- | Public token
publicToken :: PublicToken
publicToken = PublicToken "public-sandbox-e5c3a0d9-822b-4d8c-bd13-4253485c99b2"
-- | Access token
accessToken :: AccessToken
accessToken = AccessToken "access-sandbox-9e96926d-4da6-4620-a13b-c72980976436"
-- | Example of item id
itemId :: Text
itemId = "Qlr98nQgkdTQyM8agmjGt3a4RV6lKxup88BLV"
-- | Main function from which we call different api endpoints for demonstration
main :: IO ()
main = do
let env = PlaidEnv publicKey clientId sandboxSecret Sandbox
exchangeTokenResponse <- runPlaid env exampleExchangeToken
pPrint exchangeTokenResponse
authResponse <- runPlaid env exampleRetrieveAuthRequest
pPrint authResponse
transactionsResponse <- runPlaid env exampleRetrieveTransactionsRequest
pPrint transactionsResponse
identityResponse <- runPlaid env exampleIdentityRequest
pPrint identityResponse
incomeResponse <- runPlaid env exampleIncomeRequest
pPrint incomeResponse
-- | POST /item/public_token/exchange
-- https://plaid.com/docs/#exchange-token-flow
exampleExchangeToken
:: ( MonadReader PlaidEnv m
, MonadIO m
, MonadThrow m
, PlaidHttp m
)
=> m (Either PlaidError PlaidAccessTokenResponse)
exampleExchangeToken = do
-- get the plaid environment
env <- ask
runExceptT $ do
-- create the public token request body
-- this action can fail if we provide wrong parameters
publicTokenBody <- liftEither $
mkCreatePublicTokenEnv env
-- Pay attention to provide valid institution id! There is a list of valid ones
-- in the docs https:://plaid.com/docs/#investments-top-institutions-we-cover
(InstitutionId "ins_3")
-- Provide the list of plaid products or empty list
["transactions"]
-- This is optional. If you want you can setup a web-hook where plaid will send its responses.
defaultPlaidOptions
-- fire the create public token action
PlaidPublicTokenResponse {..} <- lift $ plaidCreatePublicToken publicTokenBody
-- use the response to create an exchange public token request body
-- it looks something like this:
-- @
-- PlaidBody {plaidBodyEnv = PlaidEnv {plaidEnvPublicKey = "f19293a734d8e9cc89faacb09719e5", plaidEnvClientId = ClientId {unClientId = "5d11dd0fdeb8a80013cc99e9"}, plaidEnvSecret = Secret {unSecret = "0d5e0ec25d432388f7fb34d3528394"}, plaidEnvEnvironment = sandbox}, plaidBodyPublicToken = Just (PublicToken {unPublicToken = "public-sandbox-6a6d0da0-4d53-4702-a1eb-9b430625122b"}), plaidBodyAccessToken = Nothing, plaidBodyOptions = Nothing, plaidBodyInstitutionId = Nothing, plaidBodyInitialProducts = Nothing}
-- @
exchangeBody <- liftEither (mkExchangePublicTokenEnv env _plaidPublicTokenResponsePublicToken)
-- fire exchange token action
lift $ plaidExchangeToken exchangeBody
-- if the response is successfull it looks something like this:
-- @
-- Right (PlaidAccessTokenResponse {plaidAccessTokenResponseAccessToken = "access-sandbox-0ca6b500-c682-437e-bdc9-051665b71941", plaidAccessTokenResponseRequestId = "2vBC1rv95r7Se60", plaidAccessTokenResponseItemId = "mdwNyLvv9zF655lGQ1bxikExVGb4doULb5VPp"})
-- @
getAuthBody
:: ( MonadReader PlaidEnv m
, MonadIO m
, MonadThrow m
, PlaidHttp m
)
=> m (Either PlaidError (PlaidBody AuthGet))
getAuthBody = do
env <- ask
runExceptT $ do
publicTokenBody <- liftEither $ createPublicTokenBody env
PlaidAccessTokenResponse {..} <- lift $ exchangeToken publicTokenBody
liftEither (mkGetAuthEnv env _plaidAccessTokenResponseAccessToken)
-- | POST /auth/get
-- https://plaid.com/docs/#retrieve-auth-request
exampleRetrieveAuthRequest
:: ( MonadReader PlaidEnv m
, MonadIO m
, MonadThrow m
, PlaidHttp m
)
=> m (Either PlaidError ByteString)
exampleRetrieveAuthRequest =
-- get the plaid environment
runExceptT $ do
-- create the public token request body
-- this action can fail if we provide wrong parameters
eauthBody <- lift getAuthBody
authBody <- liftEither eauthBody
lift $ plaidGetAuth authBody
-- | POST /transactions/get
-- https://plaid.com/docs/#retrieve-transactions-request
exampleRetrieveTransactionsRequest
:: ( MonadReader PlaidEnv m
, MonadIO m
, MonadThrow m
, PlaidHttp m
)
=> m (Either PlaidError ByteString)
exampleRetrieveTransactionsRequest = do
-- get the plaid environment
env <- ask
runExceptT $ do
-- create the public token request body
-- this action can fail if we provide wrong parameters
publicTokenBody <- liftEither $ createPublicTokenBody env
PlaidAccessTokenResponse {..} <- lift $ exchangeToken publicTokenBody
authBody <- liftEither (mkGetAuthEnv env _plaidAccessTokenResponseAccessToken)
_ <- lift $ plaidGetAuth authBody
let startTime = fromGregorian 2018 1 1
endTime = fromGregorian 2019 1 1
transactionBody <-
liftEither
(mkCreateTransactionsGetEnv
env
_plaidAccessTokenResponseAccessToken
startTime
endTime
Nothing
(Just defPaginationOptions)
)
lift $ plaidGetTransactions transactionBody
-- | POST /income/get
-- http://plaid.com/docs/#income
exampleIncomeRequest
:: ( MonadReader PlaidEnv m
, MonadIO m
, MonadThrow m
, PlaidHttp m
)
=> m (Either PlaidError ByteString)
exampleIncomeRequest = do
env <- ask
runExceptT $ do
-- create the public token request body
-- this action can fail if we provide wrong parameters
publicTokenBody <- liftEither $ createPublicTokenBody env
PlaidAccessTokenResponse {..} <- lift $ exchangeToken publicTokenBody
incomeBody <- liftEither (mkCreateIncomeGetEnv env _plaidAccessTokenResponseAccessToken)
lift $ plaidGetIncome incomeBody
-- | POST /identity/get
-- http://plaid.com/docs/#identity
exampleIdentityRequest
:: ( MonadReader PlaidEnv m
, MonadIO m
, MonadThrow m
, PlaidHttp m
)
=> m (Either PlaidError ByteString)
exampleIdentityRequest = do
env <- ask
runExceptT $ do
-- create the public token request body
-- this action can fail if we provide wrong parameters
publicTokenBody <- liftEither $ createPublicTokenBody env
PlaidAccessTokenResponse {..} <- lift $ exchangeToken publicTokenBody
identityBody <- liftEither (mkCreateIdentityGetEnv env _plaidAccessTokenResponseAccessToken)
lift $ plaidGetIdentity identityBody
exchangeToken
:: ( MonadReader PlaidEnv m
, MonadIO m
, MonadThrow m
, PlaidHttp m
)
=> PlaidBody PublicTokenCreate
-> m PlaidAccessTokenResponse
exchangeToken publicTokenBody = do
env <- ask
-- fire the create public token action
PlaidPublicTokenResponse {..} <- plaidCreatePublicToken publicTokenBody
case mkExchangePublicTokenEnv env _plaidPublicTokenResponsePublicToken of
Left err -> throwM err
Right exchangeBody -> plaidExchangeToken exchangeBody
createPublicTokenBody :: PlaidEnv -> Either PlaidError (PlaidBody PublicTokenCreate)
createPublicTokenBody env =
mkCreatePublicTokenEnv env
-- pay attention to provide valid institution id! There is a list of valid ones
-- in the docs https:://plaid.com/docs/#investments-top-institutions-we-cover
(InstitutionId "ins_3")
-- provide the list of plaid products or empty list
["transactions"]
-- this is optional. If you want you can setup a web-hook where plaid will send its responses.
mempty
defaultPlaidOptions :: Maybe PlaidOptions
defaultPlaidOptions =
Just $
PlaidOptions
{ _plaidOptionsWebHook = "http://bogicevicsasa.com"
, _plaidOptionsOverrideUsername = "user_good"
, _plaidOptionsOverridePassword = "pass_good"
}