packages feed

coinbase-pro 0.9.0.0 → 0.9.1.0

raw patch · 17 files changed

+490/−110 lines, 17 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- CoinbasePro.WebSocketFeed.Request: AuthenticatedWebSocketFeedRequest :: WebSocketFeedRequest -> CBAccessSign -> CBAccessKey -> CBAccessPassphrase -> CBAccessTimeStamp -> AuthenticatedWebSocketFeedRequest
- CoinbasePro.WebSocketFeed.Request: [cbKey] :: AuthenticatedWebSocketFeedRequest -> CBAccessKey
- CoinbasePro.WebSocketFeed.Request: [cbPassphrase] :: AuthenticatedWebSocketFeedRequest -> CBAccessPassphrase
- CoinbasePro.WebSocketFeed.Request: [cbSig] :: AuthenticatedWebSocketFeedRequest -> CBAccessSign
- CoinbasePro.WebSocketFeed.Request: [cbTimestamp] :: AuthenticatedWebSocketFeedRequest -> CBAccessTimeStamp
- CoinbasePro.WebSocketFeed.Request: [request] :: AuthenticatedWebSocketFeedRequest -> WebSocketFeedRequest
- CoinbasePro.WebSocketFeed.Request: instance GHC.Classes.Eq CoinbasePro.WebSocketFeed.Request.AuthenticatedWebSocketFeedRequest
+ CoinbasePro.Authenticated: createReport :: ReportRequest -> CBAuthT ClientM ReportResponse
+ CoinbasePro.Authenticated: getReport :: ReportId -> CBAuthT ClientM ReportResponse
+ CoinbasePro.Authenticated: profile :: ProfileId -> CBAuthT ClientM Profile
+ CoinbasePro.Authenticated: profileTransfer :: ProfileId -> ProfileId -> CurrencyType -> String -> CBAuthT ClientM ()
+ CoinbasePro.Authenticated: profiles :: Maybe Bool -> CBAuthT ClientM [Profile]
+ CoinbasePro.Authenticated.API: createReport :: ReportRequest -> AuthenticatedRequest (AuthProtect "CBAuth") -> ClientM ReportResponse
+ CoinbasePro.Authenticated.API: getReport :: ReportId -> AuthenticatedRequest (AuthProtect "CBAuth") -> ClientM ReportResponse
+ CoinbasePro.Authenticated.API: profile :: ProfileId -> AuthenticatedRequest (AuthProtect "CBAuth") -> ClientM Profile
+ CoinbasePro.Authenticated.API: profileTransfer :: ProfileTransfer -> AuthenticatedRequest (AuthProtect "CBAuth") -> ClientM NoContent
+ CoinbasePro.Authenticated.API: profiles :: Maybe Bool -> AuthenticatedRequest (AuthProtect "CBAuth") -> ClientM [Profile]
+ CoinbasePro.Authenticated.Profile: Profile :: ProfileId -> UserId -> Text -> Bool -> Bool -> CreatedAt -> Profile
+ CoinbasePro.Authenticated.Profile: ProfileTransfer :: ProfileId -> ProfileId -> CurrencyType -> String -> ProfileTransfer
+ CoinbasePro.Authenticated.Profile: [amount] :: ProfileTransfer -> String
+ CoinbasePro.Authenticated.Profile: [currency] :: ProfileTransfer -> CurrencyType
+ CoinbasePro.Authenticated.Profile: [from] :: ProfileTransfer -> ProfileId
+ CoinbasePro.Authenticated.Profile: [pActive] :: Profile -> Bool
+ CoinbasePro.Authenticated.Profile: [pCreatedAt] :: Profile -> CreatedAt
+ CoinbasePro.Authenticated.Profile: [pId] :: Profile -> ProfileId
+ CoinbasePro.Authenticated.Profile: [pIsDefault] :: Profile -> Bool
+ CoinbasePro.Authenticated.Profile: [pName] :: Profile -> Text
+ CoinbasePro.Authenticated.Profile: [pUserId] :: Profile -> UserId
+ CoinbasePro.Authenticated.Profile: [to] :: ProfileTransfer -> ProfileId
+ CoinbasePro.Authenticated.Profile: data Profile
+ CoinbasePro.Authenticated.Profile: data ProfileTransfer
+ CoinbasePro.Authenticated.Profile: instance Data.Aeson.Types.FromJSON.FromJSON CoinbasePro.Authenticated.Profile.Profile
+ CoinbasePro.Authenticated.Profile: instance Data.Aeson.Types.FromJSON.FromJSON CoinbasePro.Authenticated.Profile.ProfileTransfer
+ CoinbasePro.Authenticated.Profile: instance Data.Aeson.Types.ToJSON.ToJSON CoinbasePro.Authenticated.Profile.Profile
+ CoinbasePro.Authenticated.Profile: instance Data.Aeson.Types.ToJSON.ToJSON CoinbasePro.Authenticated.Profile.ProfileTransfer
+ CoinbasePro.Authenticated.Profile: instance GHC.Show.Show CoinbasePro.Authenticated.Profile.Profile
+ CoinbasePro.Authenticated.Profile: instance GHC.Show.Show CoinbasePro.Authenticated.Profile.ProfileTransfer
+ CoinbasePro.Authenticated.Report: Accounts :: AccountsReportRequest -> ReportRequest
+ CoinbasePro.Authenticated.Report: Fills :: FillsReportRequest -> ReportRequest
+ CoinbasePro.Authenticated.Report: ReportId :: UUID -> ReportId
+ CoinbasePro.Authenticated.Report: ReportResponse :: ReportId -> ReportRequestType -> ReportStatus -> Maybe CreatedAt -> Maybe UTCTime -> Maybe UTCTime -> Maybe Text -> Maybe ReportParams -> ReportResponse
+ CoinbasePro.Authenticated.Report: [rrCompletedAt] :: ReportResponse -> Maybe UTCTime
+ CoinbasePro.Authenticated.Report: [rrCreatedAt] :: ReportResponse -> Maybe CreatedAt
+ CoinbasePro.Authenticated.Report: [rrExpiresAt] :: ReportResponse -> Maybe UTCTime
+ CoinbasePro.Authenticated.Report: [rrFileUrl] :: ReportResponse -> Maybe Text
+ CoinbasePro.Authenticated.Report: [rrId] :: ReportResponse -> ReportId
+ CoinbasePro.Authenticated.Report: [rrParams] :: ReportResponse -> Maybe ReportParams
+ CoinbasePro.Authenticated.Report: [rrStatus] :: ReportResponse -> ReportStatus
+ CoinbasePro.Authenticated.Report: [rrType] :: ReportResponse -> ReportRequestType
+ CoinbasePro.Authenticated.Report: [unReportId] :: ReportId -> UUID
+ CoinbasePro.Authenticated.Report: accountsReportRequest :: AccountId -> Maybe ProductId -> UTCTime -> UTCTime -> Maybe ReportFormat -> Maybe Email -> ReportRequest
+ CoinbasePro.Authenticated.Report: data AccountsReportRequest
+ CoinbasePro.Authenticated.Report: data FillsReportRequest
+ CoinbasePro.Authenticated.Report: data ReportRequest
+ CoinbasePro.Authenticated.Report: data ReportResponse
+ CoinbasePro.Authenticated.Report: fillsReportRequest :: ProductId -> Maybe AccountId -> UTCTime -> UTCTime -> Maybe ReportFormat -> Maybe Email -> ReportRequest
+ CoinbasePro.Authenticated.Report: instance Data.Aeson.Types.FromJSON.FromJSON CoinbasePro.Authenticated.Report.Email
+ CoinbasePro.Authenticated.Report: instance Data.Aeson.Types.FromJSON.FromJSON CoinbasePro.Authenticated.Report.ReportFormat
+ CoinbasePro.Authenticated.Report: instance Data.Aeson.Types.FromJSON.FromJSON CoinbasePro.Authenticated.Report.ReportId
+ CoinbasePro.Authenticated.Report: instance Data.Aeson.Types.FromJSON.FromJSON CoinbasePro.Authenticated.Report.ReportParams
+ CoinbasePro.Authenticated.Report: instance Data.Aeson.Types.FromJSON.FromJSON CoinbasePro.Authenticated.Report.ReportRequestType
+ CoinbasePro.Authenticated.Report: instance Data.Aeson.Types.FromJSON.FromJSON CoinbasePro.Authenticated.Report.ReportResponse
+ CoinbasePro.Authenticated.Report: instance Data.Aeson.Types.FromJSON.FromJSON CoinbasePro.Authenticated.Report.ReportStatus
+ CoinbasePro.Authenticated.Report: instance Data.Aeson.Types.ToJSON.ToJSON CoinbasePro.Authenticated.Report.Email
+ CoinbasePro.Authenticated.Report: instance Data.Aeson.Types.ToJSON.ToJSON CoinbasePro.Authenticated.Report.ReportFormat
+ CoinbasePro.Authenticated.Report: instance Data.Aeson.Types.ToJSON.ToJSON CoinbasePro.Authenticated.Report.ReportId
+ CoinbasePro.Authenticated.Report: instance Data.Aeson.Types.ToJSON.ToJSON CoinbasePro.Authenticated.Report.ReportParams
+ CoinbasePro.Authenticated.Report: instance Data.Aeson.Types.ToJSON.ToJSON CoinbasePro.Authenticated.Report.ReportRequest
+ CoinbasePro.Authenticated.Report: instance Data.Aeson.Types.ToJSON.ToJSON CoinbasePro.Authenticated.Report.ReportRequestType
+ CoinbasePro.Authenticated.Report: instance Data.Aeson.Types.ToJSON.ToJSON CoinbasePro.Authenticated.Report.ReportResponse
+ CoinbasePro.Authenticated.Report: instance Data.Aeson.Types.ToJSON.ToJSON CoinbasePro.Authenticated.Report.ReportStatus
+ CoinbasePro.Authenticated.Report: instance GHC.Classes.Eq CoinbasePro.Authenticated.Report.ReportId
+ CoinbasePro.Authenticated.Report: instance GHC.Show.Show CoinbasePro.Authenticated.Report.AccountsReportRequest
+ CoinbasePro.Authenticated.Report: instance GHC.Show.Show CoinbasePro.Authenticated.Report.Email
+ CoinbasePro.Authenticated.Report: instance GHC.Show.Show CoinbasePro.Authenticated.Report.FillsReportRequest
+ CoinbasePro.Authenticated.Report: instance GHC.Show.Show CoinbasePro.Authenticated.Report.ReportFormat
+ CoinbasePro.Authenticated.Report: instance GHC.Show.Show CoinbasePro.Authenticated.Report.ReportId
+ CoinbasePro.Authenticated.Report: instance GHC.Show.Show CoinbasePro.Authenticated.Report.ReportParams
+ CoinbasePro.Authenticated.Report: instance GHC.Show.Show CoinbasePro.Authenticated.Report.ReportRequest
+ CoinbasePro.Authenticated.Report: instance GHC.Show.Show CoinbasePro.Authenticated.Report.ReportRequestType
+ CoinbasePro.Authenticated.Report: instance GHC.Show.Show CoinbasePro.Authenticated.Report.ReportResponse
+ CoinbasePro.Authenticated.Report: instance GHC.Show.Show CoinbasePro.Authenticated.Report.ReportStatus
+ CoinbasePro.Authenticated.Report: instance GHC.Show.Show CoinbasePro.Authenticated.Report.Request
+ CoinbasePro.Authenticated.Report: instance Web.Internal.HttpApiData.ToHttpApiData CoinbasePro.Authenticated.Report.ReportId
+ CoinbasePro.Authenticated.Report: newtype ReportId
+ CoinbasePro.Request: encodeRequestPath :: [Text] -> RequestPath
+ CoinbasePro.Types: instance Data.Aeson.Types.FromJSON.FromJSON CoinbasePro.Types.CryptoAddress
+ CoinbasePro.Types: instance Data.Aeson.Types.FromJSON.FromJSON CoinbasePro.Types.CurrencyType
+ CoinbasePro.Types: instance Data.Aeson.Types.ToJSON.ToJSON CoinbasePro.Types.CryptoAddress
+ CoinbasePro.Types: instance Data.Aeson.Types.ToJSON.ToJSON CoinbasePro.Types.CurrencyType
+ CoinbasePro.WebSocketFeed.Request: authenticatedWebSocketFeedRequest :: WebSocketFeedRequest -> CoinbaseProCredentials -> IO AuthenticatedWebSocketFeedRequest

Files

LICENSE view
@@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2018 Michael Dunn <michaelsdunn1@gmail.com>+Copyright (c) 2021 Michael Dunn <michaelsdunn1@gmail.com>  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal
README.md view
@@ -37,10 +37,9 @@         - [x] Payment Method         - [x] Coinbase 		- [x] Generate a Crypto Deposit Address-    - [ ] Withdrawals+    - [x] Withdrawals 		- [x] List Withdrawals 		- [x] Single Withdrawal-		- [ ] Canceled Withdrawal         - [x] Payment Method         - [x] Coinbase         - [x] Crypto@@ -53,16 +52,16 @@ 		- [x] List Accounts     - [x] Fees         - [x] Get Current Fees-    - [ ] Reports-        - [ ] Create a new report-        - [ ] Get report status-	- [ ] Profiles-		- [ ] List Profiles-		- [ ] Get a Profile-		- [ ] Create a Profile Transfer+    - [x] Reports+        - [x] Create a new report+        - [x] Get report status+	- [x] Profiles+		- [x] List Profiles+		- [x] Get a Profile+		- [x] Create a Profile Transfer     - [x] User Account         - [x] Trailing Volume-	- [ ] Margin+	- ~~[ ] Margin~~ (Disabled)[https://blog.coinbase.com/coinbase-pro-disables-margin-trading-42f5862f8a66] 	- [ ] Oracle 		- [ ] Get Oracle - Websocket Feed
changelog.md view
@@ -1,3 +1,13 @@+# Version 0.9.1.0++- Minor refactors + linting.++## Additional Features++- Added support for the following endpoints:+  - `Profiles`+  - `Reports`+ # Version 0.9.0.0  - Upgraded to lts-17.4 (ghc 8.10.4)
coinbase-pro.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 6d5d68b6e7e2760dac46a876ebbca9195bb32e0cb846b290d8db552d28a24647+-- hash: 99c50583d7d248741138631c4b28753ea1333f29565c1567516c183489a6d05d  name:           coinbase-pro-version:        0.9.0.0+version:        0.9.1.0 synopsis:       Client for Coinbase Pro description:    Client for Coinbase Pro REST and Websocket APIs category:       Web, Finance@@ -39,6 +39,8 @@       CoinbasePro.Authenticated.Limits       CoinbasePro.Authenticated.Orders       CoinbasePro.Authenticated.Payment+      CoinbasePro.Authenticated.Profile+      CoinbasePro.Authenticated.Report       CoinbasePro.Authenticated.Request       CoinbasePro.Authenticated.Transfer       CoinbasePro.Authenticated.Withdrawal
src/example/request/Main.hs view
@@ -3,11 +3,16 @@ module Main where  import           Control.Monad.IO.Class             (liftIO)+import           Data.Maybe                         (fromJust)+import           Data.Time                          (defaultTimeLocale,+                                                     parseTimeOrError)+import           Data.UUID                          (fromText)  import           CoinbasePro.Authenticated import           CoinbasePro.Authenticated.Accounts import           CoinbasePro.Authenticated.Headers import           CoinbasePro.Authenticated.Orders+import           CoinbasePro.Authenticated.Report import           CoinbasePro.Authenticated.Request import           CoinbasePro.Environment import           CoinbasePro.MarketData.Types       hiding (time)@@ -18,27 +23,38 @@  main :: IO () main = do-    run Sandbox (stats btcusd) >>= print-    run Sandbox (candles btcusd Nothing Nothing Minute) >>= print-    run Sandbox (trades btcusd) >>= print-    run Sandbox time >>= print-    run Sandbox products >>= print-    run Sandbox (aggregateOrderBook btcusd (Just Best)) >>= print-    run Sandbox (aggregateOrderBook btcusd (Just TopFifty)) >>= print-    run Sandbox (fullOrderBook btcusd) >>= print+    -- run Sandbox (stats btcusd) >>= print+    -- run Sandbox (candles btcusd Nothing Nothing Minute) >>= print+    -- run Sandbox (trades btcusd) >>= print+    -- run Sandbox time >>= print+    -- run Sandbox products >>= print+    -- run Sandbox (aggregateOrderBook btcusd (Just Best)) >>= print+    -- run Sandbox (aggregateOrderBook btcusd (Just TopFifty)) >>= print+    -- run Sandbox (fullOrderBook btcusd) >>= print     runCbAuthT (run Sandbox) cpc $ do-        accounts >>= liftIO . print-        account aid >>= liftIO . print-        accountHistory aid >>= liftIO . print-        fills (Just btcusd) Nothing >>= liftIO . print-        listOrders (Just [All]) (Just btcusd) >>= liftIO . print-        placeOrder Nothing btcusd Sell (Size 0.001) (Price 99999.00) True Nothing Nothing Nothing >>= liftIO . print-        placeOrder Nothing btcusd Buy (Size 1.0) (Price 1.00) True Nothing Nothing Nothing >>= liftIO . print-        cancelAll (Just btcusd) >>= liftIO . print+        -- resp <- createReport fillReportReq+        getReport rid >>= liftIO . print+        -- profiles Nothing >>= liftIO . print+        -- profile "94fa1f9e-131f-4295-b0d5-695b8a92c382" >>= liftIO . print+        -- accounts >>= liftIO . print+        -- account aid >>= liftIO . print+        -- accountHistory aid >>= liftIO . print+        -- fills (Just btcusd) Nothing >>= liftIO . print+        -- listOrders (Just [All]) (Just btcusd) >>= liftIO . print+        -- placeOrder Nothing btcusd Sell (Size 0.001) (Price 99999.00) True Nothing Nothing Nothing >>= liftIO . print+        -- placeOrder Nothing btcusd Buy (Size 1.0) (Price 1.00) True Nothing Nothing Nothing >>= liftIO . print+        -- cancelAll (Just btcusd) >>= liftIO . print   where-    accessKey  = CBAccessKey "accesskey"-    secretKey  = CBSecretKey "secretkey"-    passphrase = CBAccessPassphrase "passphrase"+    accessKey  = CBAccessKey "6e5972897a617f9c7807190c72019f2e"+    secretKey  = CBSecretKey "1MJfkRmYd+AgSo6SeGlKD1XZS7AkTikEagz0EKKn6hNHzY9Ff7+H2cc76E0vbzo+0yvwCNCBsIedi0QXwRSdGw=="+    passphrase = CBAccessPassphrase "83f2vnptwln"     cpc        = CoinbaseProCredentials accessKey secretKey passphrase-    aid        = AccountId "accountid"+    aid        = AccountId "74598a56-abef-4ffe-8d98-dd3c878d718d"     btcusd     = ProductId "BTC-USD"++    startDate    = parseTimeOrError False defaultTimeLocale "%Y-%m-%d" "2020-01-01"+    endDate      = parseTimeOrError False defaultTimeLocale "%Y-%m-%d" "2021-01-01"+    actReportReq = accountsReportRequest aid Nothing startDate endDate Nothing Nothing+    fillReportReq = fillsReportRequest btcusd Nothing startDate endDate Nothing Nothing++    rid = ReportId $ fromJust $ fromText "5b99f31a-7bcb-43f4-b8b3-7e1299e67a3e"
src/lib/CoinbasePro/Authenticated.hs view
@@ -1,7 +1,6 @@ {-# LANGUAGE DataKinds         #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeFamilies      #-}-{-# LANGUAGE TypeOperators     #-}  module CoinbasePro.Authenticated   ( accounts@@ -30,11 +29,16 @@   , withdrawalFeeEstimate   , paymentMethods   , coinbaseAccounts+  , profiles+  , profile+  , profileTransfer+  , createReport+  , getReport   ) where  import           Control.Monad                              (void)-import           Data.Aeson                                 (encode)-import qualified Data.ByteString.Builder                    as BB+import           Data.Aeson                                 (ToJSON, encode)+import           Data.ByteString                            (ByteString) import qualified Data.ByteString.Lazy.Char8                 as LC8 import           Data.Maybe                                 (fromMaybe) import qualified Data.Set                                   as S@@ -44,7 +48,6 @@ import           Data.UUID                                  (toText) import           Network.HTTP.Types                         (SimpleQuery,                                                              SimpleQueryItem,-                                                             encodePathSegments,                                                              methodDelete,                                                              methodGet,                                                              methodPost,@@ -73,18 +76,24 @@                                                              statuses) import           CoinbasePro.Authenticated.Payment          (PaymentMethod,                                                              PaymentMethodId (..))+import           CoinbasePro.Authenticated.Profile          (Profile,+                                                             ProfileTransfer (..))+import           CoinbasePro.Authenticated.Report           (ReportId (..),+                                                             ReportRequest (..),+                                                             ReportResponse) import           CoinbasePro.Authenticated.Request          (CBAuthT (..),                                                              authRequest) import           CoinbasePro.Authenticated.Transfer         (Transfer,                                                              TransferType (..))+ import           CoinbasePro.Authenticated.Withdrawal       (CoinbaseWithdrawalRequest (..),                                                              CryptoWithdrawalRequest (..),                                                              CryptoWithdrawalResponse,                                                              WithdrawalFeeEstimateResponse (..),                                                              WithdrawalRequest (..),                                                              WithdrawalResponse)-import           CoinbasePro.Request                        (RequestPath,-                                                             emptyBody)+import           CoinbasePro.Request                        (emptyBody,+                                                             encodeRequestPath)   import           CoinbasePro.Types                          (ClientOrderId (..),@@ -96,6 +105,7 @@                                                              ProfileId, Side,                                                              Size) + accountsPath :: Text accountsPath = "accounts" @@ -104,10 +114,38 @@ ordersPath = "orders"  -encodeRequestPath :: [Text] -> RequestPath-encodeRequestPath = LC8.toStrict . BB.toLazyByteString . encodePathSegments+depositsPath :: Text+depositsPath = "deposits"  +withdrawalsPath :: Text+withdrawalsPath = "withdrawals"+++coinbaseAccountPath :: Text+coinbaseAccountPath = "coinbase-account"+++profilesPath :: Text+profilesPath = "profiles"+++transferPath :: Text+transferPath = "transfer"+++usersPath :: Text+usersPath = "users"+++selfPath :: Text+selfPath = "self"+++reportsPath :: Text+reportsPath = "reports"++ mkSimpleQueryItem :: Show a => Text -> a -> SimpleQueryItem mkSimpleQueryItem s a = (encodeUtf8 s, encodeUtf8 $ pack (show a)) @@ -124,6 +162,10 @@ mkOrderIdQuery = optionalQuery "order_id"  +encodeBody :: (ToJSON b) => b -> ByteString+encodeBody = LC8.toStrict . encode++ -- | https://docs.pro.coinbase.com/#accounts accounts :: CBAuthT ClientM [Account] accounts = authRequest methodGet requestPath emptyBody API.accounts@@ -198,11 +240,10 @@            -> Maybe TimeInForce            -> CBAuthT ClientM Order placeOrder clordid prid sd sz price po ot stp tif =-    authRequest methodPost requestPath seBody $ API.placeOrder body+    authRequest methodPost requestPath (encodeBody body) $ API.placeOrder body   where     requestPath = encodeRequestPath [ordersPath]     body        = PlaceOrderBody clordid prid sd sz price po ot stp tif-    seBody      = LC8.toStrict $ encode body   -- | https://docs.pro.coinbase.com/#cancel-an-order@@ -244,14 +285,14 @@ trailingVolume :: CBAuthT ClientM [TrailingVolume] trailingVolume = authRequest methodGet requestPath emptyBody API.trailingVolume   where-    requestPath = encodeRequestPath ["users", "self", "trailing-volume"]+    requestPath = encodeRequestPath [usersPath, selfPath, "trailing-volume"]   -- | https://docs.pro.coinbase.com/#get-current-exchange-limits limits :: CBAuthT ClientM Limits limits = authRequest methodGet requestPath emptyBody API.limits   where-    requestPath = encodeRequestPath ["users", "self", "exchange-limits"]+    requestPath = encodeRequestPath [usersPath, selfPath, "exchange-limits"]   -- | https://docs.pro.coinbase.com/#list-deposits@@ -288,7 +329,7 @@     lmQ     = optionalQuery "limit" lm      query       = renderQuery True . simpleQueryToQuery $ typeQ <> profQ <> beforeQ <> afterQ <> lmQ-    requestPath = encodeRequestPath ["transfers"] <> query+    requestPath = encodeRequestPath [transferPath <> "s"] <> query   -- | https://docs.pro.coinbase.com/#single-deposit@@ -296,7 +337,7 @@ transfer :: PaymentMethodId -> CBAuthT ClientM Transfer transfer pmt@(PaymentMethodId p) = authRequest methodGet requestPath emptyBody $ API.transfer pmt   where-    requestPath = encodeRequestPath ["transfers", p]+    requestPath = encodeRequestPath [transferPath <> "s", p]   -- | https://docs.pro.coinbase.com/#payment-method@@ -305,11 +346,10 @@             -> PaymentMethodId             -> CBAuthT ClientM DepositResponse makeDeposit amt cur pmi =-    authRequest methodPost requestPath seBody $ API.makeDeposit body+    authRequest methodPost requestPath (encodeBody body) $ API.makeDeposit body   where-    requestPath = encodeRequestPath ["deposits", "payment-method"]+    requestPath = encodeRequestPath [depositsPath, "payment-method"]     body        = DepositRequest amt cur pmi-    seBody      = LC8.toStrict $ encode body   -- | https://docs.pro.coinbase.com/#coinbase@@ -318,11 +358,10 @@                     -> AccountId                     -> CBAuthT ClientM DepositResponse makeCoinbaseDeposit amt cur act =-    authRequest methodPost requestPath seBody $ API.makeCoinbaseDeposit body+    authRequest methodPost requestPath (encodeBody body) $ API.makeCoinbaseDeposit body   where-    requestPath = encodeRequestPath ["deposits", "coinbase-account"]+    requestPath = encodeRequestPath [depositsPath, coinbaseAccountPath]     body        = CoinbaseDepositRequest amt cur act-    seBody      = LC8.toStrict $ encode body   -- | https://docs.pro.coinbase.com/#generate-a-crypto-deposit-address@@ -330,7 +369,7 @@ cryptoDepositAddress act =     authRequest methodPost requestPath emptyBody $ API.cryptoDepositAddress act   where-    requestPath = encodeRequestPath ["coinbase-accounts", pack $ show act, "addresses"]+    requestPath = encodeRequestPath [coinbaseAccountPath <> "s", pack $ show act, "addresses"]   -- | https://docs.pro.coinbase.com/#payment-method55@@ -339,11 +378,10 @@                -> PaymentMethodId                -> CBAuthT ClientM WithdrawalResponse makeWithdrawal amt cur pmi =-    authRequest methodPost requestPath seBody $ API.makeWithdrawal body+    authRequest methodPost requestPath (encodeBody body) $ API.makeWithdrawal body   where-    requestPath = encodeRequestPath ["withdrawals", "payment-method"]+    requestPath = encodeRequestPath [withdrawalsPath, "payment-method"]     body        = WithdrawalRequest amt cur pmi-    seBody      = LC8.toStrict $ encode body   -- | https://docs.pro.coinbase.com/#coinbase56@@ -352,11 +390,10 @@                        -> AccountId                        -> CBAuthT ClientM WithdrawalResponse makeCoinbaseWithdrawal amt cur act =-    authRequest methodPost requestPath seBody $ API.makeCoinbaseWithdrawal body+    authRequest methodPost requestPath (encodeBody body) $ API.makeCoinbaseWithdrawal body   where-    requestPath = encodeRequestPath ["withdrawals", "coinbase-account"]+    requestPath = encodeRequestPath [withdrawalsPath, coinbaseAccountPath]     body        = CoinbaseWithdrawalRequest amt cur act-    seBody      = LC8.toStrict $ encode body   -- | https://docs.pro.coinbase.com/#crypto@@ -365,11 +402,10 @@                      -> Text                      -> CBAuthT ClientM CryptoWithdrawalResponse makeCryptoWithdrawal amt cur addr =-    authRequest methodPost requestPath seBody $ API.makeCryptoWithdrawal body+    authRequest methodPost requestPath (encodeBody body) $ API.makeCryptoWithdrawal body   where-    requestPath = encodeRequestPath ["withdrawals", "crypto"]+    requestPath = encodeRequestPath [withdrawalsPath, "crypto"]     body        = CryptoWithdrawalRequest amt cur addr-    seBody      = LC8.toStrict $ encode body   -- | https://docs.pro.coinbase.com/#fee-estimate@@ -383,7 +419,7 @@     addrQ = return $ mkSimpleQueryItem "crypto_address" addr      query       = renderQuery True . simpleQueryToQuery $ curQ <> addrQ-    requestPath = encodeRequestPath ["withdrawals", "fee-estimate"] <> query+    requestPath = encodeRequestPath [withdrawalsPath, "fee-estimate"] <> query   -- | https://docs.pro.coinbase.com/#list-payment-methods@@ -397,4 +433,47 @@ coinbaseAccounts :: CBAuthT ClientM [CoinbaseAccount] coinbaseAccounts = authRequest methodGet requestPath emptyBody API.coinbaseAccounts   where-    requestPath = encodeRequestPath ["coinbase-accounts"]+    requestPath = encodeRequestPath [coinbaseAccountPath <> "s"]+++-- | https://docs.pro.coinbase.com/#list-profiles+profiles :: Maybe Bool -> CBAuthT ClientM [Profile]+profiles active = authRequest methodGet requestPath emptyBody $ API.profiles active+  where+    activeQ  = optionalQuery "active" active++    query       = renderQuery True . simpleQueryToQuery $ activeQ+    requestPath = encodeRequestPath [profilesPath] <> query+++-- | https://docs.pro.coinbase.com/#get-a-profile+profile :: ProfileId -> CBAuthT ClientM Profile+profile profId = authRequest methodGet requestPath emptyBody $ API.profile profId+  where+    requestPath = encodeRequestPath [profilesPath, profId]+++-- | https://docs.pro.coinbase.com/#create-profile-transfer+profileTransfer :: ProfileId+                -> ProfileId+                -> CurrencyType+                -> String+                -> CBAuthT ClientM ()+profileTransfer fromProf toProf cur amt = void . authRequest methodPost requestPath (encodeBody body) $ API.profileTransfer body+  where+    requestPath = encodeRequestPath [profilesPath, transferPath]+    body        = ProfileTransfer fromProf toProf cur amt+++-- | https://docs.pro.coinbase.com/#create-a-new-report+createReport :: ReportRequest -> CBAuthT ClientM ReportResponse+createReport req = authRequest methodPost requestPath (encodeBody req) $ API.createReport req+  where+    requestPath = encodeRequestPath [reportsPath]+++-- | https://docs.pro.coinbase.com/#get-report-status+getReport :: ReportId -> CBAuthT ClientM ReportResponse+getReport rid = authRequest methodGet requestPath emptyBody $ API.getReport rid+  where+    requestPath = encodeRequestPath [reportsPath, toText $ unReportId rid]
src/lib/CoinbasePro/Authenticated/API.hs view
@@ -28,6 +28,11 @@     , withdrawalFeeEstimate     , paymentMethods     , coinbaseAccounts+    , profiles+    , profile+    , profileTransfer+    , createReport+    , getReport     ) where  import           Data.Proxy                                 (Proxy (..))@@ -60,6 +65,11 @@                                                              Status (..)) import           CoinbasePro.Authenticated.Payment          (PaymentMethod (..),                                                              PaymentMethodId)+import           CoinbasePro.Authenticated.Profile          (Profile,+                                                             ProfileTransfer)+import           CoinbasePro.Authenticated.Report           (ReportId,+                                                             ReportRequest (..),+                                                             ReportResponse (..)) import           CoinbasePro.Authenticated.Request          (AuthDelete,                                                              AuthGet, AuthPost) import           CoinbasePro.Authenticated.Transfer         (Transfer,@@ -112,6 +122,11 @@              :> AuthGet WithdrawalFeeEstimateResponse          :<|> "payment-methods" :> AuthGet [PaymentMethod]          :<|> "coinbase-accounts" :> AuthGet [CoinbaseAccount]+         :<|> "profiles" :> QueryParam "active" Bool :> AuthGet [Profile]+         :<|> "profiles" :> Capture "profile_id" ProfileId :> AuthGet Profile+         :<|> "profiles" :> "transfer" :> ReqBody '[JSON] ProfileTransfer :> AuthPost NoContent+         :<|> "reports" :> ReqBody '[JSON] ReportRequest :> AuthPost ReportResponse+         :<|> "reports" :> Capture "report_id" ReportId :> AuthGet ReportResponse   api :: Proxy API@@ -143,8 +158,14 @@ withdrawalFeeEstimate :: CurrencyType -> CryptoAddress -> AuthenticatedRequest (AuthProtect "CBAuth") -> ClientM WithdrawalFeeEstimateResponse paymentMethods :: AuthenticatedRequest (AuthProtect "CBAuth") -> ClientM [PaymentMethod] coinbaseAccounts :: AuthenticatedRequest (AuthProtect "CBAuth") -> ClientM [CoinbaseAccount]+profiles :: Maybe Bool -> AuthenticatedRequest (AuthProtect "CBAuth") -> ClientM [Profile]+profile :: ProfileId -> AuthenticatedRequest (AuthProtect "CBAuth") -> ClientM Profile+profileTransfer :: ProfileTransfer -> AuthenticatedRequest (AuthProtect "CBAuth") -> ClientM NoContent+createReport :: ReportRequest -> AuthenticatedRequest (AuthProtect "CBAuth") -> ClientM ReportResponse+getReport :: ReportId -> AuthenticatedRequest (AuthProtect "CBAuth") -> ClientM ReportResponse accounts   :<|> singleAccount :<|> accountHistory :<|> accountHolds :<|> listOrders :<|> getOrder :<|> getClientOrder :<|> placeOrder   :<|> cancelOrder :<|> cancelAll :<|> fills :<|> fees :<|> trailingVolume :<|> limits :<|> transfers :<|> transfer   :<|> makeDeposit :<|> makeCoinbaseDeposit :<|> cryptoDepositAddress :<|> makeWithdrawal :<|> makeCoinbaseWithdrawal-  :<|> makeCryptoWithdrawal :<|> withdrawalFeeEstimate :<|> paymentMethods :<|> coinbaseAccounts = client api+  :<|> makeCryptoWithdrawal :<|> withdrawalFeeEstimate :<|> paymentMethods :<|> coinbaseAccounts :<|> profiles :<|> profile+  :<|> profileTransfer :<|> createReport :<|> getReport = client api
src/lib/CoinbasePro/Authenticated/Fills.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE LambdaCase        #-} {-# LANGUAGE OverloadedStrings #-}  module CoinbasePro.Authenticated.Fills@@ -17,8 +18,8 @@   instance FromJSON Liquidity where-    parseJSON = withText "liquidity" $ \t ->-      case t of+    parseJSON = withText "liquidity" $+      \case         "M" -> return Maker         "T" -> return Taker         _   -> fail "parse error"
+ src/lib/CoinbasePro/Authenticated/Profile.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE TemplateHaskell #-}++module CoinbasePro.Authenticated.Profile+  ( Profile (..)+  , ProfileTransfer (..)+  ) where++import           Data.Aeson.Casing (snakeCase)+import           Data.Aeson.TH     (defaultOptions, deriveJSON,+                                    fieldLabelModifier)+import           Data.Text         (Text)++import           CoinbasePro.Types (CreatedAt, CurrencyType, ProfileId, UserId)++data Profile = Profile+    { pId        :: ProfileId+    , pUserId    :: UserId+    , pName      :: Text+    , pActive    :: Bool+    , pIsDefault :: Bool+    , pCreatedAt :: CreatedAt+    } deriving Show+++deriveJSON defaultOptions { fieldLabelModifier = snakeCase . drop 1 } ''Profile+++data ProfileTransfer = ProfileTransfer+    { from     :: ProfileId+    , to       :: ProfileId+    , currency :: CurrencyType+    , amount   :: String+    } deriving Show+++deriveJSON defaultOptions { fieldLabelModifier = snakeCase } ''ProfileTransfer
+ src/lib/CoinbasePro/Authenticated/Report.hs view
@@ -0,0 +1,195 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE LambdaCase                 #-}+{-# LANGUAGE OverloadedStrings          #-}+{-# LANGUAGE TemplateHaskell            #-}++module CoinbasePro.Authenticated.Report+  ( ReportId (..)+  , ReportRequest (..)+  , ReportResponse (..)++  , FillsReportRequest+  , AccountsReportRequest++  , accountsReportRequest+  , fillsReportRequest+  ) where++import           Data.Aeson                         (ToJSON (..), object, (.=))+import           Data.Aeson.Casing                  (snakeCase)+import           Data.Aeson.TH                      (constructorTagModifier,+                                                     defaultOptions, deriveJSON,+                                                     fieldLabelModifier,+                                                     unwrapUnaryRecords)+import qualified Data.Char                          as Char+import           Data.Text                          (Text)+import           Data.Time.Clock                    (UTCTime)+import           Data.UUID                          (UUID)+import           Servant.API                        (ToHttpApiData)++import           CoinbasePro.Authenticated.Accounts (AccountId)+import           CoinbasePro.Types                  (CreatedAt, ProductId)+++newtype ReportId = ReportId { unReportId:: UUID }+  deriving (Eq, Show, ToHttpApiData)+++deriveJSON defaultOptions+    { fieldLabelModifier = snakeCase+    , unwrapUnaryRecords = True+    } ''ReportId+++data ReportFormat = PDF | CSV+    deriving Show+++deriveJSON defaultOptions { constructorTagModifier = fmap Char.toLower } ''ReportFormat+++newtype Email = Email Text+    deriving Show+++deriveJSON defaultOptions { fieldLabelModifier = snakeCase } ''Email+++data Request = Request+    { rStartDate :: UTCTime+    , rEndDate   :: UTCTime+    , rFormat    :: Maybe ReportFormat+    , rEmail     :: Maybe Email+    } deriving Show+++data FillsReportRequest = FillsReportRequest+    { frProductId :: ProductId+    , frAccountId :: Maybe AccountId+    , frRequest   :: Request+    } deriving Show+++data AccountsReportRequest = AccountsReportRequest+    { arAccountId :: AccountId+    , arProductId :: Maybe ProductId+    , arRequest   :: Request+    } deriving Show+++data ReportRequest = Fills FillsReportRequest | Accounts AccountsReportRequest+    deriving Show+++accountsReportRequest :: AccountId+                      -> Maybe ProductId+                      -- ^ start date+                      -> UTCTime+                      -- ^ end date+                      -> UTCTime+                      -- ^ pdf or csv+                      -> Maybe ReportFormat+                      -> Maybe Email+                      -> ReportRequest+accountsReportRequest aid prid start end format =+  Accounts . AccountsReportRequest aid prid . Request start end format+++fillsReportRequest :: ProductId+                   -> Maybe AccountId+                   -- ^ start date+                   -> UTCTime+                   -- ^ end date+                   -> UTCTime+                   -- ^ pdf or csv+                   -> Maybe ReportFormat+                   -> Maybe Email+                   -> ReportRequest+fillsReportRequest prid aid start end format =+  Fills . FillsReportRequest prid aid . Request start end format+++instance ToJSON ReportRequest where+    toJSON (Fills frr) =+      object ([ "type"       .= ("fills" :: Text)+              , "start_date" .= rStartDate (frRequest frr)+              , "end_date"   .= rEndDate (frRequest frr)+              , "product_id" .= frProductId frr+              ] <> maybe mempty (\aid -> ["account_id" .= aid]) (frAccountId frr)+                <> maybe mempty (\em  -> ["email" .= em]) (rEmail (frRequest frr))+                <> maybe mempty (\fmt -> ["format" .= fmt]) (rFormat (frRequest frr))+             )+    toJSON (Accounts arr) =+      object ([ "type"       .= ("account" :: Text)+              , "start_date" .= rStartDate (arRequest arr)+              , "end_date"   .= rEndDate (arRequest arr)+              , "account_id" .= arAccountId arr+              ] <> maybe mempty (\prid -> ["product_id" .= prid]) (arProductId arr)+                <> maybe mempty (\em   -> ["email" .= em]) (rEmail (arRequest arr))+                <> maybe mempty (\fmt  -> ["format" .= fmt]) (rFormat (arRequest arr))+             )+++data ReportRequestType = FillsType | AccountType+++instance Show ReportRequestType where+    show FillsType   = "fills"+    show AccountType = "account"+++deriveJSON defaultOptions { constructorTagModifier = snakeCase . init . init . init . init } ''ReportRequestType+++data ReportStatus = Pending | Creating | Ready+++instance Show ReportStatus where+    show Pending  = "pending"+    show Creating = "creating"+    show Ready    = "ready"+++deriveJSON defaultOptions { constructorTagModifier = fmap Char.toLower+                          , fieldLabelModifier = snakeCase+                          } ''ReportStatus+++data ReportParams = ReportParams+    { startDate :: UTCTime+    , endDate   :: UTCTime+    } deriving Show+++deriveJSON defaultOptions { fieldLabelModifier = snakeCase } ''ReportParams+++{-|+  Example JSON Response:+  {+    "id": "0428b97b-bec1-429e-a94c-59232926778d",+    "type": "fills",+    "status": "pending",+    "created_at": "2015-01-06T10:34:47.000Z",+    "completed_at": undefined,+    "expires_at": "2015-01-13T10:35:47.000Z",+    "file_url": undefined,+    "params": {+        "start_date": "2014-11-01T00:00:00.000Z",+        "end_date": "2014-11-30T23:59:59.000Z"+    }+  }+-}+data ReportResponse = ReportResponse+    { rrId          :: ReportId+    , rrType        :: ReportRequestType+    , rrStatus      :: ReportStatus+    , rrCreatedAt   :: Maybe CreatedAt+    , rrCompletedAt :: Maybe UTCTime+    , rrExpiresAt   :: Maybe UTCTime+    , rrFileUrl     :: Maybe Text+    , rrParams      :: Maybe ReportParams+    } deriving Show+++deriveJSON defaultOptions { fieldLabelModifier = snakeCase . drop 2 } ''ReportResponse
src/lib/CoinbasePro/Headers.hs view
@@ -1,7 +1,6 @@ {-# LANGUAGE DataKinds                  #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE OverloadedStrings          #-}-{-# LANGUAGE TypeOperators              #-}  module CoinbasePro.Headers     ( RequiredHeader
src/lib/CoinbasePro/Request.hs view
@@ -18,19 +18,23 @@     , Runner      , emptyBody+    , encodeRequestPath     ) where -import           Control.Exception       (throw)-import           Control.Monad           (void)-import           Data.ByteString         (ByteString)-import           Data.Text               (unpack)-import           Network.HTTP.Client     (Manager, newManager)-import           Network.HTTP.Client.TLS (tlsManagerSettings)-import           Servant.API             (Get, JSON, (:>))+import           Control.Exception          (throw)+import           Control.Monad              (void)+import           Data.ByteString            (ByteString)+import qualified Data.ByteString.Builder    as BB+import qualified Data.ByteString.Lazy.Char8 as LC8+import           Data.Text                  (Text, unpack)+import           Network.HTTP.Client        (Manager, newManager)+import           Network.HTTP.Client.TLS    (tlsManagerSettings)+import           Network.HTTP.Types         (encodePathSegments)+import           Servant.API                (Get, JSON, (:>)) import           Servant.Client -import           CoinbasePro.Environment (Environment, apiEndpoint)-import           CoinbasePro.Headers     (UserAgent, UserAgentHeader)+import           CoinbasePro.Environment    (Environment, apiEndpoint)+import           CoinbasePro.Headers        (UserAgent, UserAgentHeader)   type CBGet a = UserAgentHeader :> Get '[JSON] a@@ -85,3 +89,7 @@  emptyBody :: ByteString emptyBody = ""+++encodeRequestPath :: [Text] -> RequestPath+encodeRequestPath = LC8.toStrict . BB.toLazyByteString . encodePathSegments
src/lib/CoinbasePro/Types.hs view
@@ -298,6 +298,12 @@     show (CurrencyType c) = unpack c  +deriveJSON defaultOptions+    { fieldLabelModifier = snakeCase+    , unwrapUnaryRecords = True+    } ''CurrencyType++ data Currency = Currency     { id      :: Text     , name    :: Text@@ -324,3 +330,9 @@  instance Show CryptoAddress where     show (CryptoAddress ca) = unpack ca+++deriveJSON defaultOptions+    { fieldLabelModifier = snakeCase+    , unwrapUnaryRecords = True+    } ''CryptoAddress
src/lib/CoinbasePro/Unauthenticated.hs view
@@ -1,5 +1,4 @@-{-# LANGUAGE DataKinds     #-}-{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE DataKinds #-}  module CoinbasePro.Unauthenticated    ( products
src/lib/CoinbasePro/WebSocketFeed.hs view
@@ -7,27 +7,22 @@ import           Control.Concurrent                 (forkIO) import           Control.Exception                  (Exception, throwIO) import           Control.Monad                      (forever)-import           Control.Monad.IO.Class             (liftIO) import           Data.Aeson                         (decode', encode)-import           Network.HTTP.Types                 (methodGet) import qualified Network.WebSockets                 as WS import qualified System.IO.Streams                  as Streams import           System.IO.Streams.Concurrent.Unagi (makeChanPipe) import qualified Wuss                               as WU -import           CoinbasePro.Authenticated.Request  (CoinbaseProCredentials (..),-                                                     mkCBAccessSign,-                                                     mkCBAccessTimeStamp)+import           CoinbasePro.Authenticated.Request  (CoinbaseProCredentials (..)) import           CoinbasePro.Environment            (Environment,                                                      WSConnection (..),                                                      wsEndpoint)-import           CoinbasePro.Request                (emptyBody) import           CoinbasePro.Types                  (ProductId) import           CoinbasePro.WebSocketFeed.Channel  (ChannelMessage (..))-import           CoinbasePro.WebSocketFeed.Request  (AuthenticatedWebSocketFeedRequest (..),-                                                     ChannelName (..),+import           CoinbasePro.WebSocketFeed.Request  (ChannelName (..),                                                      RequestMessageType (..),-                                                     WebSocketFeedRequest (..))+                                                     WebSocketFeedRequest (..),+                                                     authenticatedWebSocketFeedRequest)   data ParseException = ParseException deriving Show@@ -52,18 +47,11 @@     wsHost = host wsConn     wsPort = port wsConn -    mkWsRequest = maybe (return $ encode wsRequest) (fmap encode . authWsRequest)--    wsRequest = WebSocketFeedRequest Subscribe prids channels--    authWsRequest cpc' = do-        ts <- liftIO mkCBAccessTimeStamp-        let cbs = mkCBAccessSign (cbSecretKey cpc') ts methodGet authSubscriptionPath emptyBody-        return $ AuthenticatedWebSocketFeedRequest wsRequest cbs (cbAccessKey cpc') (cbAccessPassphrase cpc') ts--    authSubscriptionPath = "/users/self/verify"+    mkWsRequest   = maybe (return $ encode wsRequest) (fmap encode . authWsRequest)+    wsRequest     = WebSocketFeedRequest Subscribe prids channels+    authWsRequest = authenticatedWebSocketFeedRequest wsRequest   parseFeed :: WS.Connection -> IO ChannelMessage-parseFeed conn = maybe err return =<< (decode' <$> WS.receiveData conn)+parseFeed conn = WS.receiveData conn >>= maybe err return . decode'   where err = throwIO ParseException
src/lib/CoinbasePro/WebSocketFeed/Request.hs view
@@ -5,16 +5,25 @@   ( RequestMessageType (..)   , ChannelName(..)   , WebSocketFeedRequest (..)-  , AuthenticatedWebSocketFeedRequest (..)+  , AuthenticatedWebSocketFeedRequest++  , authenticatedWebSocketFeedRequest   ) where +import           Control.Monad.IO.Class            (liftIO) import           Data.Aeson                        (FromJSON (..), ToJSON (..),                                                     object, withText, (.=))+import           Network.HTTP.Types                (methodGet)  import           CoinbasePro.Authenticated.Headers (CBAccessKey (..),                                                     CBAccessPassphrase (..),                                                     CBAccessSign (..),                                                     CBAccessTimeStamp (..))+import           CoinbasePro.Authenticated.Request (CoinbaseProCredentials (..),+                                                    mkCBAccessSign,+                                                    mkCBAccessTimeStamp)+import           CoinbasePro.Request               (emptyBody,+                                                    encodeRequestPath) import           CoinbasePro.Types                 (ProductId)  @@ -74,13 +83,8 @@         , "channels" .= rc         ] -data AuthenticatedWebSocketFeedRequest = AuthenticatedWebSocketFeedRequest-    { request      :: WebSocketFeedRequest-    , cbSig        :: CBAccessSign-    , cbKey        :: CBAccessKey-    , cbPassphrase :: CBAccessPassphrase-    , cbTimestamp  :: CBAccessTimeStamp-    } deriving (Eq)+data AuthenticatedWebSocketFeedRequest =+  AuthenticatedWebSocketFeedRequest WebSocketFeedRequest CBAccessSign CBAccessKey CBAccessPassphrase CBAccessTimeStamp   instance ToJSON AuthenticatedWebSocketFeedRequest where@@ -93,3 +97,13 @@         , "passphrase" .= p         , "timestamp" .= t         ]++authenticatedWebSocketFeedRequest :: WebSocketFeedRequest+                                  -> CoinbaseProCredentials+                                  -> IO AuthenticatedWebSocketFeedRequest+authenticatedWebSocketFeedRequest wsRequest cpc = do+    ts <- liftIO mkCBAccessTimeStamp+    let cbs = mkCBAccessSign (cbSecretKey cpc) ts methodGet authSubscriptionPath emptyBody+    return $ AuthenticatedWebSocketFeedRequest wsRequest cbs (cbAccessKey cpc) (cbAccessPassphrase cpc) ts+  where+    authSubscriptionPath = encodeRequestPath ["users", "self", "verify"]
src/lib/CoinbasePro/WebSocketFeed/Response.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE LambdaCase        #-} {-# LANGUAGE OverloadedStrings #-}  module CoinbasePro.WebSocketFeed.Response@@ -24,8 +25,8 @@   instance FromJSON ResponseMessageType where-    parseJSON v = withText "response message type" (\t ->-      case t of+    parseJSON v = withText "response message type" (+      \case         "subscriptions" -> return Subscriptions         _               -> typeMismatch "response message type" v) v