api-monobank 0.1.2.0 → 0.1.3.0
raw patch · 5 files changed
+223/−100 lines, 5 files
Files
- LICENSE +17/−26
- README.md +21/−3
- api-monobank.cabal +75/−55
- src/Monobank/Api.hs +92/−15
- src/Monobank/Types.hs +18/−1
LICENSE view
@@ -1,30 +1,21 @@-Copyright Sergey Bushnyak (c) 2019--All rights reserved.--Redistribution and use in source and binary forms, with or without-modification, are permitted provided that the following conditions are met:+MIT License - * Redistributions of source code must retain the above copyright- notice, this list of conditions and the following disclaimer.+Copyright (c) 2019 Sergey Bushnyak - * Redistributions in binary form must reproduce the above- copyright notice, this list of conditions and the following- disclaimer in the documentation and/or other materials provided- with the distribution.+Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions: - * Neither the name of Sergey Bushnyak nor the names of other- contributors may be used to endorse or promote products derived- from this software without specific prior written permission.+The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.
README.md view
@@ -9,7 +9,9 @@ 1. [Introduction](#introduction) 2. [Public API](#public) 3. [Private API](#private)-4. [Building library](#building)+4. [Using library](#use)+5. [Example](#example)+6. [Say Thanks](#contributions) ## Introduction @@ -24,6 +26,7 @@ In the event of the exploitation of this API as corporate, the bank reserves the right to impose sanctions on the company. ## Public+ General information provided without authorization. | # |Path | Type | Params | Description | Response | Notes|@@ -62,12 +65,12 @@ | | | | `from` string; in `path` | Start of the excerpt time | | | | `to` string; in `path` | End time of the excerpt (if not, the current time will be used) -## Building+## Use - `src` - contains actual API that can be used in 3rd part apps - `app` - executable for CLI app that can be used to view current value or run continuosly -Just build repository with `stack build` and use following+Just build repository with `stack build` ``` $ stack exec -- mnb-app@@ -124,3 +127,18 @@ ```haskell `getPersonalStatement' (Just "bm90IHNvIGZhc3QgSm9obm55") "0" "1559728800" "" ```++## Example++Accumulated statement by month for the year. Implemented inside [Monolytics](https://github.com/sigrlami/monolytics) app with data collected by this API client.++++## Contributions++Say thanks, send tip:++- `monobank`: https://send.monobank.com.ua/3BNNDq3CV+- `btc`: 39oVXpsgsyW8ZgzsnX3sV7HLdtXWfT96qN+- `eth`: 0x9cDBA6bb44772259B3A3fb89cf233A147a720f34+- `xlm`: GD2FROTYXYSNOQQREYXHCXVOYWV556EM6PAHMVUHJNJEUYTUXUSNUZQ3
api-monobank.cabal view
@@ -1,61 +1,81 @@-name: api-monobank-version: 0.1.2.0--- synopsis:-description: Api client for popular Ukrainian bank - Monobank-homepage: https://github.com/sigrlami/api-monobank#readme-license: MIT-license-file: LICENSE-author: Sergey Bushnyak-maintainer: sergey.bushnyak@sigrlami.eu-copyright: Copyright: (c) 2019 Sergey Bushnyak-category: Web-build-type: Simple-extra-source-files: README.md-cabal-version: >=1.10+cabal-version: 1.12 +-- This file has been generated from package.yaml by hpack version 0.31.2.+--+-- see: https://github.com/sol/hpack+--+-- hash: aa51c2a1069f709dd41046f74707e2d679b91984ffdaaa2dea65a6377c378b13++name: api-monobank+version: 0.1.3.0+description: Api client for popular Ukrainian bank - Monobank+category: Web+homepage: https://github.com/sigrlami/api-monobank#readme+bug-reports: https://github.com/sigrlami/api-monobank/issues+author: Sergey Bushnyak+maintainer: sergey.bushnyak@sigrlami.eu+copyright: Copyright: (c) 2019 Sergey Bushnyak+license: MIT+license-file: LICENSE+build-type: Simple+extra-source-files:+ README.md++source-repository head+ type: git+ location: https://github.com/sigrlami/api-monobank+ library- hs-source-dirs: src- exposed-modules: Monobank.Api- , Monobank.Types- , Monobank.Utils- build-depends: base >= 4.7 && < 5- , aeson- , text- , time- , http-conduit- , bytestring- , servant- , servant-client- , http-client- , http-client-tls- default-language: Haskell2010+ exposed-modules:+ Monobank.Api+ Monobank.Types+ Monobank.Utils+ other-modules:+ Paths_api_monobank+ hs-source-dirs:+ src+ build-depends:+ aeson+ , base >=4.7 && <5+ , bytestring+ , http-client+ , http-client-tls+ , http-conduit+ , servant+ , servant-client+ , text+ , time+ default-language: Haskell2010 executable mnb-app- hs-source-dirs: app- main-is: Main.hs- ghc-options: -threaded -rtsopts -with-rtsopts=-N- build-depends: base- , bytestring- , http-conduit- , http-client- , aeson- , stm- , text- , time- , api-monobank- default-language: Haskell2010+ main-is: Main.hs+ other-modules:+ Paths_api_monobank+ hs-source-dirs:+ app+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-depends:+ aeson+ , api-monobank+ , base+ , bytestring+ , http-client+ , http-conduit+ , stm+ , text+ , time+ default-language: Haskell2010 test-suite mnb-app-test- type: exitcode-stdio-1.0- hs-source-dirs: tests- main-is: Spec.hs- build-depends: base- , bytestring- , hs-coindesk-api- ghc-options: -threaded -rtsopts -with-rtsopts=-N- default-language: Haskell2010---source-repository head- type: git- location: https://github.com/sigrlami/api-monobank+ type: exitcode-stdio-1.0+ main-is: Spec.hs+ other-modules:+ Paths_api_monobank+ hs-source-dirs:+ tests+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-depends:+ base+ , bytestring+ , hs-coindesk-api+ default-language: Haskell2010
src/Monobank/Api.hs view
@@ -12,7 +12,9 @@ ( getCurrencies , getCurrencyRates' , getPersonalInfo'+ , getPersonalInfoSigned' , getPersonalStatement'+ , getPersonalStatementSigned' , getPersonalStatementFull ) where @@ -57,7 +59,7 @@ -- GET /personal/statement/{account}/{from}/{to} :<|> "personal" :> "statement"- :> Header "X-Token" T.Text+ :> Header "X-Token" Token :> Capture "account" T.Text :> Capture "from" T.Text :> Capture "to" T.Text@@ -75,7 +77,67 @@ :<|> getPersonalStatement ) = client monobankAPI --------------------------------------------------------------------------------+-- Corporate API description https://api.monobank.ua/docs/corporate.html +type MonobankCorporateAPI =++ -- POST /personal/auth/request+ "personal"+ :> "auth"+ :> "request"+ :> Header "X-Key-Id" T.Text+ :> Header "X-Time" T.Text+ :> Header "X-Permissions" T.Text+ :> Header "X-Sign" T.Text+ :> Header "X-Callback" T.Text+ :> Post '[JSON] (Either String TokenRequest)++ -- Get /personal/auth/request+ :<|> "personal"+ :> "auth"+ :> "request"+ :> Header "X-Key-Id" T.Text+ :> Header "X-Time" T.Text+ :> Header "X-Permissions" T.Text+ :> Header "X-Sign" T.Text+ :> Get '[JSON] (Either String TokenRequest)++ -- GET /personal/client-info+ :<|> "personal"+ :> "client-info"+ :> Header "X-Key-Id" T.Text+ :> Header "X-Time" T.Text+ :> Header "X-Permissions" T.Text+ :> Header "X-Sign" T.Text+ :> Get '[JSON] User++ -- GET /personal/statement/{account}/{from}/{to}+ :<|> "personal"+ :> "statement"+ :> Header "X-Key-Id" T.Text+ :> Header "X-Time" T.Text+ :> Header "X-Permissions" T.Text+ :> Header "X-Sign" T.Text+ :> Capture "account" T.Text+ :> Capture "from" T.Text+ :> Capture "to" T.Text+ :> Get '[JSON] Statement++monobankCorporateAPI :: Proxy MonobankCorporateAPI+monobankCorporateAPI = Proxy++-- Derive call functions for the api+initializeAuth :: Maybe T.Text -> Maybe T.Text -> Maybe T.Text -> Maybe T.Text -> Maybe T.Text -> ClientM (Either String TokenRequest)+requestAuth :: Maybe T.Text -> Maybe T.Text -> Maybe T.Text -> Maybe T.Text -> ClientM (Either String TokenRequest)+getPersonalInfoSigned :: Maybe T.Text -> Maybe T.Text -> Maybe T.Text -> Maybe T.Text -> ClientM User+getPersonalStatementSigned :: Maybe T.Text -> Maybe T.Text -> Maybe T.Text -> Maybe T.Text -> T.Text -> T.Text -> T.Text -> ClientM Statement+( initializeAuth+ :<|> requestAuth+ :<|> getPersonalInfoSigned+ :<|> getPersonalStatementSigned ) = client monobankCorporateAPI++--------------------------------------------------------------------------------+ -- | Get a basic list of monobank currency rates -- | getCurrencyRates' :: IO (Either ServantError [CurrencyPair])@@ -88,21 +150,21 @@ -- | Ger bank user personal information -- |-getPersonalInfo' :: Maybe T.Text -- ^ unique user token+getPersonalInfo' :: Maybe Token -- ^ unique user token -> IO (Either ServantError User) getPersonalInfo' tkn = do mgr <- newManager tlsManagerSettings let env = ClientEnv mgr host Nothing runClientM (getPersonalInfo tkn) env- where- host = (BaseUrl Https endpoint 443 "")+ where+ host = (BaseUrl Https endpoint 443 "") -- | Receive an extract for the time from {to} to {to} time in seconds Unix time format. -- | The maximum time for which it is possible to extract an extract is 31 days -- | (2678400 seconds) Limit on the use of the function no more than 1 time in 60 seconds. ---getPersonalStatement' :: Maybe T.Text+getPersonalStatement' :: Maybe Token -> T.Text -> T.Text -> T.Text@@ -114,11 +176,11 @@ where host = (BaseUrl Https endpoint 443 "") -getPersonalStatement'' :: Maybe T.Text- -> T.Text- -> T.Text- -> T.Text- -> IO (Either ServantError Statement)+getPersonalStatement'' :: Maybe Token+ -> T.Text+ -> T.Text+ -> T.Text+ -> IO (Either ServantError Statement) getPersonalStatement'' tknM acc from to = do mgr <- newManager tlsManagerSettings let env = ClientEnv mgr host Nothing@@ -126,9 +188,13 @@ to' = T.init . T.pack . show . utcTimeToPOSIXSeconds $ (read (T.unpack to) :: UTCTime) putStrLn $ show from' runClientM (getPersonalStatement tknM acc from' to') env- where- host = (BaseUrl Https endpoint 443 "")+ where+ host = (BaseUrl Https endpoint 443 "") +getPersonalInfoSigned' = undefined++getPersonalStatementSigned' = undefined+ -------------------------------------------------------------------------------- -- Get a basic list of monobank currency rates.@@ -149,7 +215,18 @@ Right val -> do return $ val - -- Get Personal Statement from beginning--- 12 months will take 12 minutes-getPersonalStatementFull = undefined+-- 12 months will take 12 minutes,+getPersonalStatementFull :: Maybe Token+ -> T.Text+ -> T.Text+ -> T.Text+ -> IO (Either String Statement)+getPersonalStatementFull tknM acc from to = do+ let estimatedDownloadTime = 12 -- due to API restrictions, we can make only 1 call per minute+ putStrLn $ "monobank-api: due to API restrictions, we can make only 1 call per minute"+ putStrLn $ " operation will some time, approx ~ " ++ (show estimatedDownloadTime) ++ " min"++ -- TODO: do actual calls respetively to API restrictions++ return $ Left "Error"
src/Monobank/Types.hs view
@@ -20,8 +20,25 @@ -------------------------------------------------------------------------------- --- | Wrapper for user token from Developer's Dashboard, https://api.monobank.ua/+-- | List of errors that are coming from+--+data APIError = ErrInvalidAccount+ | ErrUknownToken+ | ErrTooManyRequests+ | ErrInternal+ | ErrMissingRequiredField+ | ErrPeriod31 --+ | ErrValueGreater --++-- | Wrapper for user token from Developer's Dashboard+-- https://api.monobank.ua/ type Token = T.Text++data TokenRequest =+ TokenRequest+ { tokenRequestId :: T.Text -- ^ token id+ , acceptUrl :: T.Text -- ^ url to show client as QR or ridrect+ } deriving (Eq, Show, Generic, FromJSON, ToJSON) data Account = Account