packages feed

api-rpc-pegnet 0.1.0.0 → 0.1.1.0

raw patch · 9 files changed

+1018/−50 lines, 9 filesdep +api-rpc-pegnetdep ~base

Dependencies added: api-rpc-pegnet

Dependency ranges changed: base

Files

README.md view
@@ -1,16 +1,26 @@-# Haskell JSON-RPC client for PegNet+# Haskell JSON-RPC client for PegNet daemon -[![Build Status](https://travis-ci.com/kompendium-llc/api-rpc-factom.svg?branch=master)](https://travis-ci.com/kompendium-llc/api-rpc-factom)+[![Build Status](https://travis-ci.com/kompendium-llc/pegnetd-haskell-client.svg?branch=master)](https://travis-ci.com/kompendium-llc/api-rpc-pegnet)+[![Coverage Status](https://camo.githubusercontent.com/22e3c6a06327a75d482f0ac8a06bddcd2b2574b5/68747470733a2f2f696d672e736869656c64732e696f2f636f766572616c6c732f7368696e6e6e2f697374616e62756c2d636f766572616c6c732e737667)](https://coveralls.io/github/kompendium-llc/pegnetd-haskell-client?branch=master)+![Hackage](https://img.shields.io/hackage/v/api-rpc-pegnet) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/kompendium-llc/api-rpc-factom/blob/master/LICENSE) -A JSON-RPC Haskell client for the PegNet [API](https://github.com/pegnet/pegnetd/wiki/API). Each response has special ADT(algebraic data type) that automatically converted from JSON response.+A JSON-RPC Haskell client for the PegNet [API](https://github.com/pegnet/pegnetd/wiki/API) daemon. Allows retrieval of data from PegNet dApp. Each response has special ADT(algebraic data type) that automatically converted from JSON response. Using [Remote Monad](https://ku-fpg.github.io/files/Gill-15-RemoteMonad.pdf) pattern multiple request can be batched and executed simulatenously, following more robust approach and reducing usage of expensive RPC calls. -# Installation+Choosing a batching strategy. There are two strategies:+- `Weak`   - a single command or a single procedure, or+- `Strong` - a sequence of commands, optionally terminated by a procedure -You can install package from [Hackage](https://hackage.haskell.org/package/api-rpc-factom) and build with Cabal, but we recommend to use [Stack](https://haskellstack.org) tool. Add to you dependencies in stack.yaml and cabal file dependency `- api-rpc-factom`.+1. [Installation](#installation)+2. [Usage](#usage)+3. [Contributions](#contributions) -To run and test fromrepository+## Installation +You can install package from [Hackage](https://hackage.haskell.org/package/api-rpc-pegnet) and build with Cabal, but we recommend to use [Stack](https://haskellstack.org) tool. Add to you dependencies in stack.yaml and cabal file dependency `- api-rpc-pegnet`.++To run and test from repository:+ 1. Build with stack ```bash $ stack build@@ -36,23 +46,45 @@  2. build communication session with ```-weakSession (traceSendAPI "" $ clientSendAPI endpoint)+weakSession (traceSendAPI "" $ clientSendAPIWithAlt endpoint) ```  3. run required methods inside `RPC` monad -#### Retreiving a sync status+## Usage -```haskell--- build communication session-let s = weakSession (traceSendAPI "" $ clientSendAPI endpoint)+You can construct simple session with all methods available for further processings. Check following execution --- run Remote Monad-h <- send s $ do-         -- run specific events by executing exposed+```haskell+main = do+  -- build communication session+  let s = weakSession $ traceSendAPI "" $ clientSendAPIWithAlt endpointRemote+  (h, i) <- send s $ do          h <- reqGetSyncStatus-         return h--- show converted ADT-print h--- or use for special business logic+         i <- reqPegNetIssuance+         b <- reqPegNetBalances "FA38cwer93mmPw1HxjScLmK1yF9iJTu5P87T2vdkbuLovm2YXyss"+         t <- reqGetTransaction "0-e4380e6334b0c42d4d6155fbd1378050b91c02a0df93d7fdfe6656f94c61e7eb"+         r <- reqPegNetRates 213000+         s <- reqGetTransactionStatus "a33d4f334a2658c17d3f44158af75f1c32cc6b2f3de9ddc337064c93043d8db0"+         rich <- reqGetRichList (Just "PEG") 5++         -- return values as N-ary tuple+         return (h, i)+  -- process resulted values+  print h+  -- or use for special business logic ```++Variables `h` and `i` mapped to exact data stucture. All types available for detailed overview in `Types` directory.++## Contributions++Please, feel free to contribute, fork the repo and submit PR.+++Say thanks, send a tip:++- `btc`: 39oVXpsgsyW8ZgzsnX3sV7HLdtXWfT96qN+- `fct`: FA38cwer93mmPw1HxjScLmK1yF9iJTu5P87T2vdkbuLovm2YXyss+- `eth`: 0x9cDBA6bb44772259B3A3fb89cf233A147a720f34+- `xlm`: GD2FROTYXYSNOQQREYXHCXVOYWV556EM6PAHMVUHJNJEUYTUXUSNUZQ3
api-rpc-pegnet.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: f998af876ee380cd0f3e17213282441322f7618fb4ea71159e87d583bb7e2f57+-- hash: fb6ef3f983f51f7adfb76bafdf6c7e81d8542bd82b78244f3cd8fbafe9fdffa4  name:           api-rpc-pegnet-version:        0.1.0.0+version:        0.1.1.0 synopsis:       simple json-rpc client for PegNet description:    simple json-rpc client for PegNet integration category:       Web@@ -31,8 +31,13 @@       PegNet.RPC.Api   other-modules:       PegNet.RPC.Types+      PegNet.RPC.Types.Balances+      PegNet.RPC.Types.Issuance+      PegNet.RPC.Types.Rates+      PegNet.RPC.Types.RichEntry       PegNet.RPC.Types.SyncStatus       PegNet.RPC.Types.Transaction+      PegNet.RPC.Types.TransactionStatus       Paths_api_rpc_pegnet   hs-source-dirs:       src@@ -40,6 +45,33 @@       aeson     , aeson-casing     , base >=4.7 && <5+    , bytestring+    , http-client+    , http-client-tls+    , http-conduit+    , json-alt+    , network+    , remote-json+    , remote-json-client+    , remote-monad+    , text+    , time+    , transformers+  default-language: Haskell2010++test-suite factom-test+  type: exitcode-stdio-1.0+  main-is: Spec.hs+  other-modules:+      Paths_api_rpc_pegnet+  hs-source-dirs:+      tests+  ghc-options: -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      aeson+    , aeson-casing+    , api-rpc-pegnet+    , base     , bytestring     , http-client     , http-client-tls
src/PegNet/RPC/Api.hs view
@@ -12,7 +12,7 @@ module PegNet.RPC.Api where  import           Control.Concurrent-import           Control.Exception                (bracket)+import           Control.Exception                  (bracket) import           Control.Monad.IO.Class import           Control.Remote.Monad.JSON import           Control.Remote.Monad.JSON.Client@@ -21,20 +21,28 @@ import           Data.Aeson import           Data.Aeson.Types import           Data.Text-import           Network.Socket                   (HostName, ServiceName,-                                                   SocketType (Stream),-                                                   addrAddress, addrFamily,-                                                   addrProtocol, addrSocketType,-                                                   close, connect, defaultHints,-                                                   getAddrInfo, socket)+import           Network.Socket                     (HostName, ServiceName,+                                                     SocketType (Stream),+                                                     addrAddress, addrFamily,+                                                     addrProtocol,+                                                     addrSocketType, close,+                                                     connect, defaultHints,+                                                     getAddrInfo, socket) +import           PegNet.RPC.Types.Balances+import           PegNet.RPC.Types.Issuance+import           PegNet.RPC.Types.Rates+import           PegNet.RPC.Types.RichEntry import           PegNet.RPC.Types.SyncStatus import           PegNet.RPC.Types.Transaction+import           PegNet.RPC.Types.TransactionStatus  -------------------------------------------------------------------------------- -endpoint  = "http://localhost:8070/v1"-endpointRemote = "http://dev.pegnet.org/v1"+-- | Simple endpoint wrappers to use as different+--   local or remotte API endoint, keep default values+endpoint       = "http://localhost:8070/v1"+endpointRemote = "https://api.pegnetd.com"  -- | "get-sync-status" --   Return the current heights synced by pegnetd and the factomd it is communicating with@@ -43,36 +51,105 @@   method "get-sync-status" None -- $ List [toJSON height]  -- | "get-transaction"---   Returns if a given entry hash is a pegnet transaction, and if so returns the transaction.-reqGetTransaction :: Text -> Text -> RPC Transaction-reqGetTransaction chainId entryHash =-  method "get-transaction" $ List [String chainId, String entryHash]+--   Returns the given pegnet transaction if it exists.+reqGetTransaction :: Text             -- ^ Transaction id+                  -> RPC Transaction  -- ^ Requested Transaction+reqGetTransaction txid =+  method "get-transaction"+    $ Named [("txid", String txid)] -reqPegNetIssuance :: RPC ()+-- | Get the total supply for each pegnet asset.+--+reqPegNetIssuance :: RPC NetIssuance reqPegNetIssuance =   method "get-pegnet-issuance" None -reqPegNetBalances :: RPC ()-reqPegNetBalances =-  method "get-pegnet-balances" None+-- | Get the pegnet asset balances for a given address+--+reqPegNetBalances :: Text             -- ^ Address to get balances from+                  -> RPC NetBalances  -- ^ Resulting balances over all assets+reqPegNetBalances address =+  method "get-pegnet-balances"+    $ Named [("address", String address)] -reqPegNetRates :: RPC ()-reqPegNetRates =-  method "get-pegnet-rates" None+-- | "get-pegnet-rates"+--   Returns the pegnet conversion rates for a given block height.+reqPegNetRates :: Int           -- ^ Specified height to get rates at+               -> RPC Rates     -- ^ Resulted Rates+reqPegNetRates height =+  method "get-pegnet-rates"+    $ Named [("height", toJSON height)] -reqGetTransactionStatus :: Text -> RPC ()-reqGetTransactionStatus id =-  method "get-transaction-status" None+-- | "get-transaction-status"+--   Returns the status of a transaction.+--   The parameter `entryhash` can be either a winning OPR entry hash,+--   a transaction chain entry hash, or an FCT Burn transaction id.+reqGetTransactionStatus :: Text                    -- ^ Transaction chain entry hash+                        -> RPC TransactionStatus   -- ^ Current status of transaction+reqGetTransactionStatus entryHash =+  method "get-transaction-status"+    $ Named [("entryhash", String entryHash)] -reqGeTransactions :: RPC [Transaction]-reqGeTransactions =-  method "get-transactions" None+-- | get-transactions+--   Returns a set of up to 50 transactions for the given parameters.+--   TODO: this many arguments including boolean combination is a case+--         for a bad API design. Better hide it with convinience functions+--         provided to library user+reqGetTransactions :: Maybe Text        -- ^+                   -> Maybe Text        -- ^+                   -> Maybe Int         -- ^+                   -> Maybe Int         -- ^ offset+                   -> Maybe Bool        -- ^+                   -> Maybe Bool        -- ^+                   -> Maybe Bool        -- ^+                   -> Maybe Bool        -- ^+                   -> Maybe Bool        -- ^+                   -> RPC [Transaction] -- ^ List of Transactions by specified parameters+reqGetTransactions mbEntryHash mbAddress mbHeight mbOffset b1 b2 b3 b4 b5 =+  method "get-transactions"+    $ Named ([]+     ++ (case mbEntryHash of+           Nothing -> []+           Just eh -> [("entryhash", String eh)])+     ++ (case mbAddress of+           Nothing -> []+           Just ad -> [("address", String ad)])+     ++ (case mbHeight of+           Nothing -> []+           Just hg -> [("height", toJSON hg)])) ++-- | "get-rich-list"+--   Returns the rich list of addresses for all assets or a specific asset.+reqGetRichList :: Maybe Text  -- ^ Asset name, exclude to list by all assets+               -> Int         -- ^ Number to limit from top+               -> RPC [RichEntry]+reqGetRichList mbAsset limit =+  method "get-rich-list"+    $ Named ([("count", toJSON limit)]+             ++ (case mbAsset of+                   Nothing    -> []+                   Just asset -> [("asset", String asset)]))++ -------------------------------------------------------------------------------- +-- Testing access functionality+-- NB: Factom and PegNet API return results with `plain\text` headers, we+--     need to use alternative client to handle conversion issues, since Wreq+--     library automatically throws and error for responses that are not `application\json` main = do-  let s = weakSession (traceSendAPI "" $ clientSendAPI endpoint)-  h <- send s $ do+  let s = weakSession $ traceSendAPI "" $ clientSendAPIWithAlt endpointRemote+  (h, i) <- send s $ do          h <- reqGetSyncStatus-         return h-  print h+         i <- reqPegNetIssuance+         --b <- reqPegNetBalances "FA38cwer93mmPw1HxjScLmK1yF9iJTu5P87T2vdkbuLovm2YXyss"+         --t <- reqGetTransaction "0-e4380e6334b0c42d4d6155fbd1378050b91c02a0df93d7fdfe6656f94c61e7eb"+         --r <- reqPegNetRates 213000+         -- s <- reqGetTransactionStatus "a33d4f334a2658c17d3f44158af75f1c32cc6b2f3de9ddc337064c93043d8db0"+         rich <- reqGetRichList (Just "PEG") 5+         return (h, i)+  -- process resulted values+  --print h+  --print i+  return ()
+ src/PegNet/RPC/Types/Balances.hs view
@@ -0,0 +1,224 @@+{-# LANGUAGE DeriveGeneric       #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeOperators       #-}++module PegNet.RPC.Types.Balances where++import           Control.Applicative+import           Control.Monad                   (forM_, join, mzero)+import           Data.Aeson                      (FromJSON (..), ToJSON (..),+                                                  Value (..), decode, object,+                                                  pairs, (.:), (.:?), (.=))+import           Data.Aeson.AutoType.Alternative+import qualified Data.ByteString.Lazy.Char8      as BSL+import           Data.Monoid+import           Data.Text                       (Text)+import qualified GHC.Generics+import           System.Environment              (getArgs)+import           System.Exit                     (exitFailure, exitSuccess)+import           System.IO                       (hPutStrLn, stderr)++--------------------------------------------------------------------------------++-- | Workaround for https://github.com/bos/aeson/issues/287.+o .:?? val = fmap join (o .:? val)+++data NetBalances = NetBalances {+    topLevelPBRL  :: Double,+    topLevelPRVN  :: Double,+    topLevelPEUR  :: Double,+    topLevelPUSD  :: Double,+    topLevelPEG   :: Double,+    topLevelPCHF  :: Double,+    topLevelPDCR  :: Double,+    topLevelPLTC  :: Double,+    topLevelPMXN  :: Double,+    topLevelPKRW  :: Double,+    topLevelPXBT  :: Double,+    topLevelPBNB  :: Double,+    topLevelPCAD  :: Double,+    topLevelPZEC  :: Double,+    topLevelPXAU  :: Double,+    topLevelPADA  :: Double,+    topLevelPCNY  :: Double,+    topLevelPXMR  :: Double,+    topLevelPHKD  :: Double,+    topLevelPINR  :: Double,+    topLevelPGBP  :: Double,+    topLevelPSGD  :: Double,+    topLevelPPHP  :: Double,+    topLevelPJPY  :: Double,+    topLevelPDASH :: Double,+    topLevelPXAG  :: Double,+    topLevelPXBC  :: Double,+    topLevelPFCT  :: Double,+    topLevelPXLM  :: Double,+    topLevelPETH  :: Double+  } deriving (Show,Eq,GHC.Generics.Generic)+++instance FromJSON NetBalances where+  parseJSON (Object v) =+    NetBalances+      <$> v+      .:  "pBRL"+      <*> v+      .:  "pRVN"+      <*> v+      .:  "pEUR"+      <*> v+      .:  "pUSD"+      <*> v+      .:  "PEG"+      <*> v+      .:  "pCHF"+      <*> v+      .:  "pDCR"+      <*> v+      .:  "pLTC"+      <*> v+      .:  "pMXN"+      <*> v+      .:  "pKRW"+      <*> v+      .:  "pXBT"+      <*> v+      .:  "pBNB"+      <*> v+      .:  "pCAD"+      <*> v+      .:  "pZEC"+      <*> v+      .:  "pXAU"+      <*> v+      .:  "pADA"+      <*> v+      .:  "pCNY"+      <*> v+      .:  "pXMR"+      <*> v+      .:  "pHKD"+      <*> v+      .:  "pINR"+      <*> v+      .:  "pGBP"+      <*> v+      .:  "pSGD"+      <*> v+      .:  "pPHP"+      <*> v+      .:  "pJPY"+      <*> v+      .:  "pDASH"+      <*> v+      .:  "pXAG"+      <*> v+      .:  "pXBC"+      <*> v+      .:  "pFCT"+      <*> v+      .:  "pXLM"+      <*> v+      .:  "pETH"+  parseJSON _ = mzero+++instance ToJSON NetBalances where+  toJSON (NetBalances {..}) = object+    [ "pBRL" .= topLevelPBRL+    , "pRVN" .= topLevelPRVN+    , "pEUR" .= topLevelPEUR+    , "pUSD" .= topLevelPUSD+    , "PEG" .= topLevelPEG+    , "pCHF" .= topLevelPCHF+    , "pDCR" .= topLevelPDCR+    , "pLTC" .= topLevelPLTC+    , "pMXN" .= topLevelPMXN+    , "pKRW" .= topLevelPKRW+    , "pXBT" .= topLevelPXBT+    , "pBNB" .= topLevelPBNB+    , "pCAD" .= topLevelPCAD+    , "pZEC" .= topLevelPZEC+    , "pXAU" .= topLevelPXAU+    , "pADA" .= topLevelPADA+    , "pCNY" .= topLevelPCNY+    , "pXMR" .= topLevelPXMR+    , "pHKD" .= topLevelPHKD+    , "pINR" .= topLevelPINR+    , "pGBP" .= topLevelPGBP+    , "pSGD" .= topLevelPSGD+    , "pPHP" .= topLevelPPHP+    , "pJPY" .= topLevelPJPY+    , "pDASH" .= topLevelPDASH+    , "pXAG" .= topLevelPXAG+    , "pXBC" .= topLevelPXBC+    , "pFCT" .= topLevelPFCT+    , "pXLM" .= topLevelPXLM+    , "pETH" .= topLevelPETH+    ]+  toEncoding (NetBalances {..}) = pairs+    (  "pBRL"+    .= topLevelPBRL+    <> "pRVN"+    .= topLevelPRVN+    <> "pEUR"+    .= topLevelPEUR+    <> "pUSD"+    .= topLevelPUSD+    <> "PEG"+    .= topLevelPEG+    <> "pCHF"+    .= topLevelPCHF+    <> "pDCR"+    .= topLevelPDCR+    <> "pLTC"+    .= topLevelPLTC+    <> "pMXN"+    .= topLevelPMXN+    <> "pKRW"+    .= topLevelPKRW+    <> "pXBT"+    .= topLevelPXBT+    <> "pBNB"+    .= topLevelPBNB+    <> "pCAD"+    .= topLevelPCAD+    <> "pZEC"+    .= topLevelPZEC+    <> "pXAU"+    .= topLevelPXAU+    <> "pADA"+    .= topLevelPADA+    <> "pCNY"+    .= topLevelPCNY+    <> "pXMR"+    .= topLevelPXMR+    <> "pHKD"+    .= topLevelPHKD+    <> "pINR"+    .= topLevelPINR+    <> "pGBP"+    .= topLevelPGBP+    <> "pSGD"+    .= topLevelPSGD+    <> "pPHP"+    .= topLevelPPHP+    <> "pJPY"+    .= topLevelPJPY+    <> "pDASH"+    .= topLevelPDASH+    <> "pXAG"+    .= topLevelPXAG+    <> "pXBC"+    .= topLevelPXBC+    <> "pFCT"+    .= topLevelPFCT+    <> "pXLM"+    .= topLevelPXLM+    <> "pETH"+    .= topLevelPETH+    )
+ src/PegNet/RPC/Types/Issuance.hs view
@@ -0,0 +1,267 @@+{-# LANGUAGE DeriveGeneric       #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeOperators       #-}++module PegNet.RPC.Types.Issuance where++import           Control.Applicative+import           Control.Monad                   (forM_, join, mzero)+import           Data.Aeson                      (FromJSON (..), ToJSON (..),+                                                  Value (..), decode, object,+                                                  pairs, (.:), (.:?), (.=))+import           Data.Aeson.AutoType.Alternative+import qualified Data.ByteString.Lazy.Char8      as BSL+import           Data.Monoid+import           Data.Text                       (Text)+import qualified GHC.Generics+import           System.Environment              (getArgs)+import           System.Exit                     (exitFailure, exitSuccess)+import           System.IO                       (hPutStrLn, stderr)++--------------------------------------------------------------------------------++-- | Workaround for https://github.com/bos/aeson/issues/287.+o .:?? val = fmap join (o .:? val)+++data Issuance = Issuance {+    issuancePBRL  :: Double,+    issuancePRVN  :: Double,+    issuancePEUR  :: Double,+    issuancePUSD  :: Double,+    issuancePEG   :: Double,+    issuancePCHF  :: Double,+    issuancePDCR  :: Double,+    issuancePLTC  :: Double,+    issuancePMXN  :: Double,+    issuancePKRW  :: Double,+    issuancePXBT  :: Double,+    issuancePBNB  :: Double,+    issuancePCAD  :: Double,+    issuancePZEC  :: Double,+    issuancePXAU  :: Double,+    issuancePADA  :: Double,+    issuancePCNY  :: Double,+    issuancePXMR  :: Double,+    issuancePHKD  :: Double,+    issuancePINR  :: Double,+    issuancePGBP  :: Double,+    issuancePSGD  :: Double,+    issuancePPHP  :: Double,+    issuancePJPY  :: Double,+    issuancePDASH :: Double,+    issuancePXAG  :: Double,+    issuancePXBC  :: Double,+    issuancePFCT  :: Double,+    issuancePXLM  :: Double,+    issuancePETH  :: Double+  } deriving (Show,Eq,GHC.Generics.Generic)+++instance FromJSON Issuance where+  parseJSON (Object v) =+    Issuance+      <$> v+      .:  "pBRL"+      <*> v+      .:  "pRVN"+      <*> v+      .:  "pEUR"+      <*> v+      .:  "pUSD"+      <*> v+      .:  "PEG"+      <*> v+      .:  "pCHF"+      <*> v+      .:  "pDCR"+      <*> v+      .:  "pLTC"+      <*> v+      .:  "pMXN"+      <*> v+      .:  "pKRW"+      <*> v+      .:  "pXBT"+      <*> v+      .:  "pBNB"+      <*> v+      .:  "pCAD"+      <*> v+      .:  "pZEC"+      <*> v+      .:  "pXAU"+      <*> v+      .:  "pADA"+      <*> v+      .:  "pCNY"+      <*> v+      .:  "pXMR"+      <*> v+      .:  "pHKD"+      <*> v+      .:  "pINR"+      <*> v+      .:  "pGBP"+      <*> v+      .:  "pSGD"+      <*> v+      .:  "pPHP"+      <*> v+      .:  "pJPY"+      <*> v+      .:  "pDASH"+      <*> v+      .:  "pXAG"+      <*> v+      .:  "pXBC"+      <*> v+      .:  "pFCT"+      <*> v+      .:  "pXLM"+      <*> v+      .:  "pETH"+  parseJSON _ = mzero+++instance ToJSON Issuance where+  toJSON (Issuance {..}) = object+    [ "pBRL" .= issuancePBRL+    , "pRVN" .= issuancePRVN+    , "pEUR" .= issuancePEUR+    , "pUSD" .= issuancePUSD+    , "PEG" .= issuancePEG+    , "pCHF" .= issuancePCHF+    , "pDCR" .= issuancePDCR+    , "pLTC" .= issuancePLTC+    , "pMXN" .= issuancePMXN+    , "pKRW" .= issuancePKRW+    , "pXBT" .= issuancePXBT+    , "pBNB" .= issuancePBNB+    , "pCAD" .= issuancePCAD+    , "pZEC" .= issuancePZEC+    , "pXAU" .= issuancePXAU+    , "pADA" .= issuancePADA+    , "pCNY" .= issuancePCNY+    , "pXMR" .= issuancePXMR+    , "pHKD" .= issuancePHKD+    , "pINR" .= issuancePINR+    , "pGBP" .= issuancePGBP+    , "pSGD" .= issuancePSGD+    , "pPHP" .= issuancePPHP+    , "pJPY" .= issuancePJPY+    , "pDASH" .= issuancePDASH+    , "pXAG" .= issuancePXAG+    , "pXBC" .= issuancePXBC+    , "pFCT" .= issuancePFCT+    , "pXLM" .= issuancePXLM+    , "pETH" .= issuancePETH+    ]+  toEncoding (Issuance {..}) = pairs+    (  "pBRL"+    .= issuancePBRL+    <> "pRVN"+    .= issuancePRVN+    <> "pEUR"+    .= issuancePEUR+    <> "pUSD"+    .= issuancePUSD+    <> "PEG"+    .= issuancePEG+    <> "pCHF"+    .= issuancePCHF+    <> "pDCR"+    .= issuancePDCR+    <> "pLTC"+    .= issuancePLTC+    <> "pMXN"+    .= issuancePMXN+    <> "pKRW"+    .= issuancePKRW+    <> "pXBT"+    .= issuancePXBT+    <> "pBNB"+    .= issuancePBNB+    <> "pCAD"+    .= issuancePCAD+    <> "pZEC"+    .= issuancePZEC+    <> "pXAU"+    .= issuancePXAU+    <> "pADA"+    .= issuancePADA+    <> "pCNY"+    .= issuancePCNY+    <> "pXMR"+    .= issuancePXMR+    <> "pHKD"+    .= issuancePHKD+    <> "pINR"+    .= issuancePINR+    <> "pGBP"+    .= issuancePGBP+    <> "pSGD"+    .= issuancePSGD+    <> "pPHP"+    .= issuancePPHP+    <> "pJPY"+    .= issuancePJPY+    <> "pDASH"+    .= issuancePDASH+    <> "pXAG"+    .= issuancePXAG+    <> "pXBC"+    .= issuancePXBC+    <> "pFCT"+    .= issuancePFCT+    <> "pXLM"+    .= issuancePXLM+    <> "pETH"+    .= issuancePETH+    )+++data Syncstatus = Syncstatus {+    syncstatusFactomheight :: Double,+    syncstatusSyncheight   :: Double+  } deriving (Show,Eq,GHC.Generics.Generic)+++instance FromJSON Syncstatus where+  parseJSON (Object v) =+    Syncstatus <$> v .: "factomheight" <*> v .: "syncheight"+  parseJSON _ = mzero+++instance ToJSON Syncstatus where+  toJSON (Syncstatus {..}) = object+    [ "factomheight" .= syncstatusFactomheight+    , "syncheight" .= syncstatusSyncheight+    ]+  toEncoding (Syncstatus {..}) = pairs+    (  "factomheight"+    .= syncstatusFactomheight+    <> "syncheight"+    .= syncstatusSyncheight+    )+++data NetIssuance = NetIssuance {+    topLevelIssuance   :: Issuance,+    topLevelSyncstatus :: Syncstatus+  } deriving (Show,Eq,GHC.Generics.Generic)+++instance FromJSON NetIssuance where+  parseJSON (Object v) = NetIssuance <$> v .: "issuance" <*> v .: "syncstatus"+  parseJSON _          = mzero+++instance ToJSON NetIssuance where+  toJSON (NetIssuance {..}) =+    object ["issuance" .= topLevelIssuance, "syncstatus" .= topLevelSyncstatus]+  toEncoding (NetIssuance {..}) =+    pairs ("issuance" .= topLevelIssuance <> "syncstatus" .= topLevelSyncstatus)
+ src/PegNet/RPC/Types/Rates.hs view
@@ -0,0 +1,224 @@+{-# LANGUAGE DeriveGeneric       #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeOperators       #-}++module PegNet.RPC.Types.Rates where++import           Control.Applicative+import           Control.Monad                   (forM_, join, mzero)+import           Data.Aeson                      (FromJSON (..), ToJSON (..),+                                                  Value (..), decode, object,+                                                  pairs, (.:), (.:?), (.=))+import           Data.Aeson.AutoType.Alternative+import qualified Data.ByteString.Lazy.Char8      as BSL+import           Data.Monoid+import           Data.Text                       (Text)+import qualified GHC.Generics+import           System.Environment              (getArgs)+import           System.Exit                     (exitFailure, exitSuccess)+import           System.IO                       (hPutStrLn, stderr)++--------------------------------------------------------------------------------++-- | Workaround for https://github.com/bos/aeson/issues/287.+o .:?? val = fmap join (o .:? val)+++data Rates = Rates {+    ratePBRL  :: Double,+    ratePRVN  :: Double,+    ratePEUR  :: Double,+    ratePUSD  :: Double,+    ratePEG   :: Double,+    ratePCHF  :: Double,+    ratePDCR  :: Double,+    ratePLTC  :: Double,+    ratePMXN  :: Double,+    ratePKRW  :: Double,+    ratePXBT  :: Double,+    ratePBNB  :: Double,+    ratePCAD  :: Double,+    ratePZEC  :: Double,+    ratePXAU  :: Double,+    ratePADA  :: Double,+    ratePCNY  :: Double,+    ratePXMR  :: Double,+    ratePHKD  :: Double,+    ratePINR  :: Double,+    ratePGBP  :: Double,+    ratePSGD  :: Double,+    ratePPHP  :: Double,+    ratePJPY  :: Double,+    ratePDASH :: Double,+    ratePXAG  :: Double,+    ratePXBC  :: Double,+    ratePFCT  :: Double,+    ratePXLM  :: Double,+    ratePETH  :: Double+  } deriving (Show,Eq,GHC.Generics.Generic)+++instance FromJSON Rates where+  parseJSON (Object v) =+    Rates+      <$> v+      .:  "pBRL"+      <*> v+      .:  "pRVN"+      <*> v+      .:  "pEUR"+      <*> v+      .:  "pUSD"+      <*> v+      .:  "PEG"+      <*> v+      .:  "pCHF"+      <*> v+      .:  "pDCR"+      <*> v+      .:  "pLTC"+      <*> v+      .:  "pMXN"+      <*> v+      .:  "pKRW"+      <*> v+      .:  "pXBT"+      <*> v+      .:  "pBNB"+      <*> v+      .:  "pCAD"+      <*> v+      .:  "pZEC"+      <*> v+      .:  "pXAU"+      <*> v+      .:  "pADA"+      <*> v+      .:  "pCNY"+      <*> v+      .:  "pXMR"+      <*> v+      .:  "pHKD"+      <*> v+      .:  "pINR"+      <*> v+      .:  "pGBP"+      <*> v+      .:  "pSGD"+      <*> v+      .:  "pPHP"+      <*> v+      .:  "pJPY"+      <*> v+      .:  "pDASH"+      <*> v+      .:  "pXAG"+      <*> v+      .:  "pXBC"+      <*> v+      .:  "pFCT"+      <*> v+      .:  "pXLM"+      <*> v+      .:  "pETH"+  parseJSON _ = mzero+++instance ToJSON Rates where+  toJSON (Rates {..}) = object+    [ "pBRL" .= ratePBRL+    , "pRVN" .= ratePRVN+    , "pEUR" .= ratePEUR+    , "pUSD" .= ratePUSD+    , "PEG" .= ratePEG+    , "pCHF" .= ratePCHF+    , "pDCR" .= ratePDCR+    , "pLTC" .= ratePLTC+    , "pMXN" .= ratePMXN+    , "pKRW" .= ratePKRW+    , "pXBT" .= ratePXBT+    , "pBNB" .= ratePBNB+    , "pCAD" .= ratePCAD+    , "pZEC" .= ratePZEC+    , "pXAU" .= ratePXAU+    , "pADA" .= ratePADA+    , "pCNY" .= ratePCNY+    , "pXMR" .= ratePXMR+    , "pHKD" .= ratePHKD+    , "pINR" .= ratePINR+    , "pGBP" .= ratePGBP+    , "pSGD" .= ratePSGD+    , "pPHP" .= ratePPHP+    , "pJPY" .= ratePJPY+    , "pDASH" .= ratePDASH+    , "pXAG" .= ratePXAG+    , "pXBC" .= ratePXBC+    , "pFCT" .= ratePFCT+    , "pXLM" .= ratePXLM+    , "pETH" .= ratePETH+    ]+  toEncoding (Rates {..}) = pairs+    (  "pBRL"+    .= ratePBRL+    <> "pRVN"+    .= ratePRVN+    <> "pEUR"+    .= ratePEUR+    <> "pUSD"+    .= ratePUSD+    <> "PEG"+    .= ratePEG+    <> "pCHF"+    .= ratePCHF+    <> "pDCR"+    .= ratePDCR+    <> "pLTC"+    .= ratePLTC+    <> "pMXN"+    .= ratePMXN+    <> "pKRW"+    .= ratePKRW+    <> "pXBT"+    .= ratePXBT+    <> "pBNB"+    .= ratePBNB+    <> "pCAD"+    .= ratePCAD+    <> "pZEC"+    .= ratePZEC+    <> "pXAU"+    .= ratePXAU+    <> "pADA"+    .= ratePADA+    <> "pCNY"+    .= ratePCNY+    <> "pXMR"+    .= ratePXMR+    <> "pHKD"+    .= ratePHKD+    <> "pINR"+    .= ratePINR+    <> "pGBP"+    .= ratePGBP+    <> "pSGD"+    .= ratePSGD+    <> "pPHP"+    .= ratePPHP+    <> "pJPY"+    .= ratePJPY+    <> "pDASH"+    .= ratePDASH+    <> "pXAG"+    .= ratePXAG+    <> "pXBC"+    .= ratePXBC+    <> "pFCT"+    .= ratePFCT+    <> "pXLM"+    .= ratePXLM+    <> "pETH"+    .= ratePETH+    )
+ src/PegNet/RPC/Types/RichEntry.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE DeriveGeneric       #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeOperators       #-}++module PegNet.RPC.Types.RichEntry where++import           Control.Applicative+import           Control.Monad                   (forM_, join, mzero)+import           Data.Aeson                      (FromJSON (..), ToJSON (..),+                                                  Value (..), decode, object,+                                                  pairs, (.:), (.:?), (.=))+import           Data.Aeson.AutoType.Alternative+import qualified Data.ByteString.Lazy.Char8      as BSL+import           Data.Monoid+import           Data.Text                       (Text)+import qualified GHC.Generics+import           System.Environment              (getArgs)+import           System.Exit                     (exitFailure, exitSuccess)+import           System.IO                       (hPutStrLn, stderr)++--------------------------------------------------------------------------------++data RichEntry =+  RichEntry+    { reAmount  :: Int+    , rePusd    :: Int+    , reAddress :: Text+    } deriving (Show, Eq, GHC.Generics.Generic)++instance FromJSON RichEntry where+  parseJSON (Object v) =+    RichEntry+      <$> v .:  "amount"+      <*> v .:  "pusd"+      <*> v .:  "address"+  parseJSON _ = mzero++instance ToJSON RichEntry where+  toJSON (RichEntry {..}) =+    object [ "amount"  .= reAmount+           , "pusd"    .= rePusd+           , "address" .= reAddress+           ]+  toEncoding (RichEntry {..}) =+    pairs  (   "amount"  .= reAmount+            <> "pusd"    .= rePusd+            <> "address" .= reAddress)
+ src/PegNet/RPC/Types/TransactionStatus.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE DeriveGeneric       #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeOperators       #-}++module PegNet.RPC.Types.TransactionStatus where++import           Control.Applicative+import           Control.Monad                   (forM_, join, mzero)+import           Data.Aeson                      (FromJSON (..), ToJSON (..),+                                                  Value (..), decode, object,+                                                  pairs, (.:), (.:?), (.=))+import           Data.Aeson.AutoType.Alternative+import qualified Data.ByteString.Lazy.Char8      as BSL+import           Data.Monoid+import           Data.Text                       (Text)+import qualified GHC.Generics+import           System.Environment              (getArgs)+import           System.Exit                     (exitFailure, exitSuccess)+import           System.IO                       (hPutStrLn, stderr)++--------------------------------------------------------------------------------++data TransactionStatus =+  TransactionStatus {+    txHeight   :: Int,+    txExecuted :: Int+  } deriving (Show,Eq,GHC.Generics.Generic)++instance FromJSON TransactionStatus where+  parseJSON (Object v) =+    TransactionStatus+      <$> v .: "height"+      <*> v .: "executed"+  parseJSON _          = mzero++instance ToJSON TransactionStatus where+  toJSON (TransactionStatus {..}) =+    object [ "height" .= txHeight+           , "executed" .= txExecuted+           ]+  toEncoding (TransactionStatus {..}) =+    pairs  (    "height"   .= txHeight+             <> "executed" .= txExecuted+           )
+ tests/Spec.hs view
@@ -0,0 +1,15 @@+import Test.Hspec+import Test.QuickCheck+import Control.Exception (evaluate)++main :: IO ()+main = hspec $ do+  describe "Prelude.head" $ do+    it "returns the first element of a list" $ do+      head [23 ..] `shouldBe` (23 :: Int)++    it "returns the first element of an *arbitrary* list" $+      property $ \x xs -> head (x:xs) == (x :: Int)++    it "throws an exception if used with an empty list" $ do+      evaluate (head []) `shouldThrow` anyException