{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE RecordWildCards #-}
{-| This module contains the @main@ function used by the exectuable.

-}
module Console.SolanaStaking.Main
    ( run
    , getArgs
    , Args(..)
    ) where

import           Control.Monad                  ( (<=<)
                                                , forM
                                                , unless
                                                )
import           Control.Monad.Except           ( ExceptT
                                                , runExceptT
                                                )
import           Control.Monad.Reader           ( ReaderT
                                                , liftIO
                                                , runReaderT
                                                )
import           Data.Bifunctor                 ( bimap
                                                , second
                                                )
import           Data.List                      ( sortOn )
import           Data.Maybe                     ( fromMaybe )
import           Data.Version                   ( showVersion )
import           System.Console.CmdArgs         ( (&=)
                                                , Data
                                                , Typeable
                                                , argPos
                                                , cmdArgs
                                                , def
                                                , explicit
                                                , help
                                                , helpArg
                                                , name
                                                , program
                                                , summary
                                                , typ
                                                )
import           System.IO                      ( hPutStrLn
                                                , stderr
                                                )

import           Console.SolanaStaking.Api
import           Console.SolanaStaking.CoinTracking
                                                ( makeCoinTrackingImport )
import           Console.SolanaStaking.Csv      ( makeCsvContents )
import           Paths_solana_staking_csvs      ( version )

import qualified Data.ByteString.Lazy          as LBS


-- | Pull staking rewards data for the account & print a CSV to stdout.
--
-- TODO: concurrent/pooled requests, but w/ 100 req/s limit
run :: Args -> IO ()
run :: Args -> IO ()
run Args {Bool
String
Maybe String
argCoinTracking :: Args -> Bool
argOutputFile :: Args -> Maybe String
argPubKey :: Args -> String
argApiKey :: Args -> String
argCoinTracking :: Bool
argOutputFile :: Maybe String
argPubKey :: String
argApiKey :: String
..} = (APIError -> IO ()) -> (() -> IO ()) -> Either APIError () -> IO ()
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (String -> IO ()
forall a. HasCallStack => String -> a
error (String -> IO ()) -> (APIError -> String) -> APIError -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. APIError -> String
forall a. Show a => a -> String
show) () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return (Either APIError () -> IO ())
-> (ReaderT Config (ExceptT APIError IO) ()
    -> IO (Either APIError ()))
-> ReaderT Config (ExceptT APIError IO) ()
-> IO ()
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< ReaderT Config (ExceptT APIError IO) () -> IO (Either APIError ())
forall a.
ReaderT Config (ExceptT APIError IO) a -> IO (Either APIError a)
runner (ReaderT Config (ExceptT APIError IO) () -> IO ())
-> ReaderT Config (ExceptT APIError IO) () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
    -- Grab all stake accounts
    [StakingAccount]
stakes <- StakingAccounts -> [StakingAccount]
saResults (StakingAccounts -> [StakingAccount])
-> ReaderT Config (ExceptT APIError IO) StakingAccounts
-> ReaderT Config (ExceptT APIError IO) [StakingAccount]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (ReaderT Config (ExceptT APIError IO) (APIResponse StakingAccounts)
forall (m :: * -> *).
(MonadIO m, MonadReader Config m) =>
m (APIResponse StakingAccounts)
getAccountStakes ReaderT Config (ExceptT APIError IO) (APIResponse StakingAccounts)
-> (APIResponse StakingAccounts
    -> ReaderT Config (ExceptT APIError IO) StakingAccounts)
-> ReaderT Config (ExceptT APIError IO) StakingAccounts
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= APIResponse StakingAccounts
-> ReaderT Config (ExceptT APIError IO) StakingAccounts
forall (m :: * -> *) a.
MonadError APIError m =>
APIResponse a -> m a
raiseAPIError)
    -- Grab rewards for each stake account
    ([APIError]
stakeErrors, [(StakingAccount, StakeReward)]
stakeRewards) <-
        ([([APIError], [(StakingAccount, StakeReward)])]
 -> ([APIError], [(StakingAccount, StakeReward)]))
-> ReaderT
     Config
     (ExceptT APIError IO)
     [([APIError], [(StakingAccount, StakeReward)])]
-> ReaderT
     Config
     (ExceptT APIError IO)
     ([APIError], [(StakingAccount, StakeReward)])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (([[APIError]] -> [APIError])
-> ([[(StakingAccount, StakeReward)]]
    -> [(StakingAccount, StakeReward)])
-> ([[APIError]], [[(StakingAccount, StakeReward)]])
-> ([APIError], [(StakingAccount, StakeReward)])
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap [[APIError]] -> [APIError]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[(StakingAccount, StakeReward)]]
-> [(StakingAccount, StakeReward)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (([[APIError]], [[(StakingAccount, StakeReward)]])
 -> ([APIError], [(StakingAccount, StakeReward)]))
-> ([([APIError], [(StakingAccount, StakeReward)])]
    -> ([[APIError]], [[(StakingAccount, StakeReward)]]))
-> [([APIError], [(StakingAccount, StakeReward)])]
-> ([APIError], [(StakingAccount, StakeReward)])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [([APIError], [(StakingAccount, StakeReward)])]
-> ([[APIError]], [[(StakingAccount, StakeReward)]])
forall a b. [(a, b)] -> ([a], [b])
unzip) (ReaderT
   Config
   (ExceptT APIError IO)
   [([APIError], [(StakingAccount, StakeReward)])]
 -> ReaderT
      Config
      (ExceptT APIError IO)
      ([APIError], [(StakingAccount, StakeReward)]))
-> ((StakingAccount
     -> ReaderT
          Config
          (ExceptT APIError IO)
          ([APIError], [(StakingAccount, StakeReward)]))
    -> ReaderT
         Config
         (ExceptT APIError IO)
         [([APIError], [(StakingAccount, StakeReward)])])
-> (StakingAccount
    -> ReaderT
         Config
         (ExceptT APIError IO)
         ([APIError], [(StakingAccount, StakeReward)]))
-> ReaderT
     Config
     (ExceptT APIError IO)
     ([APIError], [(StakingAccount, StakeReward)])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [StakingAccount]
-> (StakingAccount
    -> ReaderT
         Config
         (ExceptT APIError IO)
         ([APIError], [(StakingAccount, StakeReward)]))
-> ReaderT
     Config
     (ExceptT APIError IO)
     [([APIError], [(StakingAccount, StakeReward)])]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [StakingAccount]
stakes ((StakingAccount
  -> ReaderT
       Config
       (ExceptT APIError IO)
       ([APIError], [(StakingAccount, StakeReward)]))
 -> ReaderT
      Config
      (ExceptT APIError IO)
      ([APIError], [(StakingAccount, StakeReward)]))
-> (StakingAccount
    -> ReaderT
         Config
         (ExceptT APIError IO)
         ([APIError], [(StakingAccount, StakeReward)]))
-> ReaderT
     Config
     (ExceptT APIError IO)
     ([APIError], [(StakingAccount, StakeReward)])
forall a b. (a -> b) -> a -> b
$ \StakingAccount
sa -> do
            ([StakeReward] -> [(StakingAccount, StakeReward)])
-> ([APIError], [StakeReward])
-> ([APIError], [(StakingAccount, StakeReward)])
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second ((StakeReward -> (StakingAccount, StakeReward))
-> [StakeReward] -> [(StakingAccount, StakeReward)]
forall a b. (a -> b) -> [a] -> [b]
map (StakingAccount
sa, )) (([APIError], [StakeReward])
 -> ([APIError], [(StakingAccount, StakeReward)]))
-> ReaderT Config (ExceptT APIError IO) ([APIError], [StakeReward])
-> ReaderT
     Config
     (ExceptT APIError IO)
     ([APIError], [(StakingAccount, StakeReward)])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StakingPubKey
-> ReaderT Config (ExceptT APIError IO) ([APIError], [StakeReward])
forall (m :: * -> *).
(MonadIO m, MonadReader Config m) =>
StakingPubKey -> m ([APIError], [StakeReward])
getAllStakeRewards (StakingAccount -> StakingPubKey
saPubKey StakingAccount
sa)
    Bool
-> ReaderT Config (ExceptT APIError IO) ()
-> ReaderT Config (ExceptT APIError IO) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([APIError] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [APIError]
stakeErrors) (ReaderT Config (ExceptT APIError IO) ()
 -> ReaderT Config (ExceptT APIError IO) ())
-> (IO () -> ReaderT Config (ExceptT APIError IO) ())
-> IO ()
-> ReaderT Config (ExceptT APIError IO) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO () -> ReaderT Config (ExceptT APIError IO) ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ReaderT Config (ExceptT APIError IO) ())
-> IO () -> ReaderT Config (ExceptT APIError IO) ()
forall a b. (a -> b) -> a -> b
$ do
        Handle -> String -> IO ()
hPutStrLn Handle
stderr String
"Got errors while fetching stake rewards:"
        (APIError -> IO ()) -> [APIError] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (Handle -> String -> IO ()
hPutStrLn Handle
stderr (String -> IO ()) -> (APIError -> String) -> APIError -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"\t" String -> String -> String
forall a. Semigroup a => a -> a -> a
<>) (String -> String) -> (APIError -> String) -> APIError -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. APIError -> String
forall a. Show a => a -> String
show) [APIError]
stakeErrors
    -- Write the CSV
    let orderedRewards :: [(StakingAccount, StakeReward)]
orderedRewards = ((StakingAccount, StakeReward) -> POSIXTime)
-> [(StakingAccount, StakeReward)]
-> [(StakingAccount, StakeReward)]
forall b a. Ord b => (a -> b) -> [a] -> [a]
sortOn (StakeReward -> POSIXTime
srTimestamp (StakeReward -> POSIXTime)
-> ((StakingAccount, StakeReward) -> StakeReward)
-> (StakingAccount, StakeReward)
-> POSIXTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (StakingAccount, StakeReward) -> StakeReward
forall a b. (a, b) -> b
snd) [(StakingAccount, StakeReward)]
stakeRewards
        outputFile :: String
outputFile     = String -> Maybe String -> String
forall a. a -> Maybe a -> a
fromMaybe String
"-" Maybe String
argOutputFile
    if Bool
argCoinTracking
        then IO () -> ReaderT Config (ExceptT APIError IO) ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ReaderT Config (ExceptT APIError IO) ())
-> IO () -> ReaderT Config (ExceptT APIError IO) ()
forall a b. (a -> b) -> a -> b
$ String -> [(StakingAccount, StakeReward)] -> IO ()
makeCoinTrackingImport String
outputFile [(StakingAccount, StakeReward)]
orderedRewards
        else do
            let output :: ByteString
output = [(StakingAccount, StakeReward)] -> ByteString
makeCsvContents [(StakingAccount, StakeReward)]
orderedRewards
            if String
outputFile String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"-"
                then IO () -> ReaderT Config (ExceptT APIError IO) ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ReaderT Config (ExceptT APIError IO) ())
-> IO () -> ReaderT Config (ExceptT APIError IO) ()
forall a b. (a -> b) -> a -> b
$ ByteString -> IO ()
LBS.putStr ByteString
output
                else IO () -> ReaderT Config (ExceptT APIError IO) ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ReaderT Config (ExceptT APIError IO) ())
-> IO () -> ReaderT Config (ExceptT APIError IO) ()
forall a b. (a -> b) -> a -> b
$ String -> ByteString -> IO ()
LBS.writeFile String
outputFile ByteString
output
  where
    runner :: ReaderT Config (ExceptT APIError IO) a -> IO (Either APIError a)
    runner :: ReaderT Config (ExceptT APIError IO) a -> IO (Either APIError a)
runner = ExceptT APIError IO a -> IO (Either APIError a)
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT (ExceptT APIError IO a -> IO (Either APIError a))
-> (ReaderT Config (ExceptT APIError IO) a
    -> ExceptT APIError IO a)
-> ReaderT Config (ExceptT APIError IO) a
-> IO (Either APIError a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ReaderT Config (ExceptT APIError IO) a
 -> Config -> ExceptT APIError IO a)
-> Config
-> ReaderT Config (ExceptT APIError IO) a
-> ExceptT APIError IO a
forall a b c. (a -> b -> c) -> b -> a -> c
flip ReaderT Config (ExceptT APIError IO) a
-> Config -> ExceptT APIError IO a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (String -> String -> Config
mkConfig String
argApiKey String
argPubKey)


-- | CLI arguments supported by the executable.
data Args = Args
    { Args -> String
argApiKey       :: String
    -- ^ Solana Beach API Key
    , Args -> String
argPubKey       :: String
    -- ^ Delegator's PubKey.
    , Args -> Maybe String
argOutputFile   :: Maybe String
    -- ^ Optional output file. 'Nothing' or @'Just' "-"@ means print to
    -- 'System.IO.stdout'.
    , Args -> Bool
argCoinTracking :: Bool
    -- ^ Flag to enable writing/printing files formatted for CoinTracking
    -- Imports.
    }
    deriving (Int -> Args -> String -> String
[Args] -> String -> String
Args -> String
(Int -> Args -> String -> String)
-> (Args -> String) -> ([Args] -> String -> String) -> Show Args
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [Args] -> String -> String
$cshowList :: [Args] -> String -> String
show :: Args -> String
$cshow :: Args -> String
showsPrec :: Int -> Args -> String -> String
$cshowsPrec :: Int -> Args -> String -> String
Show, ReadPrec [Args]
ReadPrec Args
Int -> ReadS Args
ReadS [Args]
(Int -> ReadS Args)
-> ReadS [Args] -> ReadPrec Args -> ReadPrec [Args] -> Read Args
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Args]
$creadListPrec :: ReadPrec [Args]
readPrec :: ReadPrec Args
$creadPrec :: ReadPrec Args
readList :: ReadS [Args]
$creadList :: ReadS [Args]
readsPrec :: Int -> ReadS Args
$creadsPrec :: Int -> ReadS Args
Read, Args -> Args -> Bool
(Args -> Args -> Bool) -> (Args -> Args -> Bool) -> Eq Args
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Args -> Args -> Bool
$c/= :: Args -> Args -> Bool
== :: Args -> Args -> Bool
$c== :: Args -> Args -> Bool
Eq, Typeable Args
DataType
Constr
Typeable Args
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Args -> c Args)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Args)
-> (Args -> Constr)
-> (Args -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c Args))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Args))
-> ((forall b. Data b => b -> b) -> Args -> Args)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Args -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Args -> r)
-> (forall u. (forall d. Data d => d -> u) -> Args -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> Args -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Args -> m Args)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Args -> m Args)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Args -> m Args)
-> Data Args
Args -> DataType
Args -> Constr
(forall b. Data b => b -> b) -> Args -> Args
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Args -> c Args
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Args
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> Args -> u
forall u. (forall d. Data d => d -> u) -> Args -> [u]
forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Args -> r
forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Args -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Args -> m Args
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Args -> m Args
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Args
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Args -> c Args
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Args)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Args)
$cArgs :: Constr
$tArgs :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> Args -> m Args
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Args -> m Args
gmapMp :: (forall d. Data d => d -> m d) -> Args -> m Args
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Args -> m Args
gmapM :: (forall d. Data d => d -> m d) -> Args -> m Args
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Args -> m Args
gmapQi :: Int -> (forall d. Data d => d -> u) -> Args -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Args -> u
gmapQ :: (forall d. Data d => d -> u) -> Args -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Args -> [u]
gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Args -> r
$cgmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Args -> r
gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Args -> r
$cgmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Args -> r
gmapT :: (forall b. Data b => b -> b) -> Args -> Args
$cgmapT :: (forall b. Data b => b -> b) -> Args -> Args
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Args)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Args)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c Args)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Args)
dataTypeOf :: Args -> DataType
$cdataTypeOf :: Args -> DataType
toConstr :: Args -> Constr
$ctoConstr :: Args -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Args
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Args
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Args -> c Args
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Args -> c Args
$cp1Data :: Typeable Args
Data, Typeable)

-- | Parse the CLI arguments with 'System.Console.CmdArgs'.
getArgs :: IO Args
getArgs :: IO Args
getArgs = Args -> IO Args
forall a. Data a => a -> IO a
cmdArgs Args
argSpec

argSpec :: Args
argSpec :: Args
argSpec =
    Args :: String -> String -> Maybe String -> Bool -> Args
Args
            { argApiKey :: String
argApiKey       = String
forall a. Default a => a
def String -> Ann -> String
forall val. Data val => val -> Ann -> val
&= Int -> Ann
argPos Int
0 String -> Ann -> String
forall val. Data val => val -> Ann -> val
&= String -> Ann
typ String
"API_KEY"
            , argPubKey :: String
argPubKey       = String
forall a. Default a => a
def String -> Ann -> String
forall val. Data val => val -> Ann -> val
&= Int -> Ann
argPos Int
1 String -> Ann -> String
forall val. Data val => val -> Ann -> val
&= String -> Ann
typ String
"ACCOUNT_PUBKEY"
            , argOutputFile :: Maybe String
argOutputFile   =
                Maybe String
forall a. Maybe a
Nothing
                Maybe String -> Ann -> Maybe String
forall val. Data val => val -> Ann -> val
&= String -> Ann
help String
"File to write the export to. Default: stdout"
                Maybe String -> Ann -> Maybe String
forall val. Data val => val -> Ann -> val
&= Ann
explicit
                Maybe String -> Ann -> Maybe String
forall val. Data val => val -> Ann -> val
&= String -> Ann
name String
"output-file"
                Maybe String -> Ann -> Maybe String
forall val. Data val => val -> Ann -> val
&= String -> Ann
name String
"o"
                Maybe String -> Ann -> Maybe String
forall val. Data val => val -> Ann -> val
&= String -> Ann
typ String
"FILE"
            , argCoinTracking :: Bool
argCoinTracking = Bool
False
                                Bool -> Ann -> Bool
forall val. Data val => val -> Ann -> val
&= String -> Ann
help String
"Generate a CoinTracking Import file."
                                Bool -> Ann -> Bool
forall val. Data val => val -> Ann -> val
&= Ann
explicit
                                Bool -> Ann -> Bool
forall val. Data val => val -> Ann -> val
&= String -> Ann
name String
"cointracking"
            }
        Args -> Ann -> Args
forall val. Data val => val -> Ann -> val
&= String -> Ann
summary
               (  String
"solana-staking-csvs v"
               String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Version -> String
showVersion Version
version
               String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
", Pavan Rikhi 2021"
               )
        Args -> Ann -> Args
forall val. Data val => val -> Ann -> val
&= String -> Ann
program String
"solana-staking-csvs"
        Args -> Ann -> Args
forall val. Data val => val -> Ann -> val
&= [Ann] -> Ann
helpArg [String -> Ann
name String
"h"]
        Args -> Ann -> Args
forall val. Data val => val -> Ann -> val
&= String -> Ann
help String
"Generate CSV Exports of your Solana Staking Rewards."