{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} module PegNet.RPC.Api where import Control.Concurrent import Control.Exception (bracket) import Control.Monad.IO.Class import Control.Remote.Monad.JSON import Control.Remote.Monad.JSON.Client import Control.Remote.Monad.JSON.Router import Control.Remote.Monad.JSON.Trace 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 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 -------------------------------------------------------------------------------- -- | 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 reqGetSyncStatus :: RPC SyncStatus reqGetSyncStatus = method "get-sync-status" None -- | "get-transaction" -- 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)] -- | Get the total supply for each pegnet asset. -- reqPegNetIssuance :: RPC NetIssuance reqPegNetIssuance = method "get-pegnet-issuance" 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)] -- | "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)] -- | "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)] -- | 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 "" $ clientSendAPIWithAlt endpointRemote (h, i) <- send s $ do h <- reqGetSyncStatus 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 ()