{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE RecordWildCards #-}

-- | CLI application harness.
module Console.BnbStaking.Main
    ( run
    , getArgs
    , Args (..)
    ) where

import Control.Monad (filterM, foldM, (<=<))
import Data.Maybe (fromMaybe, mapMaybe)
import Data.Time (localDay, toGregorian, utcToLocalZonedTime, zonedTimeToLocalTime)
import Data.Version (showVersion)
import Network.HTTP.Req (defaultHttpConfig, runReq)
import System.Console.CmdArgs
    ( Data
    , Typeable
    , argPos
    , cmdArgs
    , def
    , explicit
    , help
    , helpArg
    , name
    , program
    , summary
    , typ
    , (&=)
    )

import Console.BnbStaking.Api (Reward (..), getAllRewards)
import Console.BnbStaking.CoinTracking (makeCoinTrackingImport)
import Console.BnbStaking.Csv (makeCsvContents)
import Paths_bnb_staking_csvs (version)

import Data.ByteString.Lazy.Char8 qualified as LBC
import Data.List qualified as L
import Data.Map.Strict qualified as M
import Data.Text qualified as T


-- | Run the executable - parsing args, making queries, & printing the
-- results.
run :: Args -> IO ()
run :: Args -> IO ()
run Args {Bool
String
Maybe Integer
Maybe String
argPubKey :: String
argOutputFile :: Maybe String
argCoinTracking :: Bool
argYear :: Maybe Integer
argAggregate :: Bool
argPubKey :: Args -> String
argOutputFile :: Args -> Maybe String
argCoinTracking :: Args -> Bool
argYear :: Args -> Maybe Integer
argAggregate :: Args -> Bool
..} = do
    let aggregator :: [Reward] -> IO [Reward]
aggregator = if Bool
argAggregate then [Reward] -> IO [Reward]
aggregateRewards else [Reward] -> IO [Reward]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return
        filterer :: [Reward] -> IO [Reward]
filterer = ([Reward] -> IO [Reward])
-> (Integer -> [Reward] -> IO [Reward])
-> Maybe Integer
-> [Reward]
-> IO [Reward]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [Reward] -> IO [Reward]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Integer -> [Reward] -> IO [Reward]
filterByYear Maybe Integer
argYear
    [Reward]
rewards <-
        [Reward] -> IO [Reward]
filterer ([Reward] -> IO [Reward])
-> (Req [Reward] -> IO [Reward]) -> Req [Reward] -> IO [Reward]
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< [Reward] -> IO [Reward]
aggregator ([Reward] -> IO [Reward])
-> (Req [Reward] -> IO [Reward]) -> Req [Reward] -> IO [Reward]
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< HttpConfig -> Req [Reward] -> IO [Reward]
forall (m :: * -> *) a. MonadIO m => HttpConfig -> Req a -> m a
runReq HttpConfig
defaultHttpConfig (Req [Reward] -> IO [Reward]) -> Req [Reward] -> IO [Reward]
forall a b. (a -> b) -> a -> b
$
            Text -> Req [Reward]
forall (m :: * -> *). MonadHttp m => Text -> m [Reward]
getAllRewards (String -> Text
T.pack String
argPubKey)
    let outputFile :: String
outputFile = String -> Maybe String -> String
forall a. a -> Maybe a -> a
fromMaybe String
"-" Maybe String
argOutputFile
    if Bool
argCoinTracking
        then String -> String -> [Reward] -> IO ()
makeCoinTrackingImport String
outputFile String
argPubKey [Reward]
rewards
        else do
            -- TODO: we calculate local zoned day in filterByYear & in
            -- makeCsvContents. Can we do it just once?
            ByteString
output <- [Reward] -> IO ByteString
makeCsvContents [Reward]
rewards
            if String
outputFile String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"-"
                then ByteString -> IO ()
LBC.putStr ByteString
output
                else String -> ByteString -> IO ()
LBC.writeFile String
outputFile ByteString
output
  where
    aggregateRewards :: [Reward] -> IO [Reward]
    aggregateRewards :: [Reward] -> IO [Reward]
aggregateRewards =
        (Map Day [Reward] -> [Reward])
-> IO (Map Day [Reward]) -> IO [Reward]
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (((Day, [Reward]) -> Maybe Reward) -> [(Day, [Reward])] -> [Reward]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe ([Reward] -> Maybe Reward
aggregate ([Reward] -> Maybe Reward)
-> ((Day, [Reward]) -> [Reward]) -> (Day, [Reward]) -> Maybe Reward
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Day, [Reward]) -> [Reward]
forall a b. (a, b) -> b
snd) ([(Day, [Reward])] -> [Reward])
-> (Map Day [Reward] -> [(Day, [Reward])])
-> Map Day [Reward]
-> [Reward]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map Day [Reward] -> [(Day, [Reward])]
forall k a. Map k a -> [(k, a)]
M.toList)
            (IO (Map Day [Reward]) -> IO [Reward])
-> ([Reward] -> IO (Map Day [Reward])) -> [Reward] -> IO [Reward]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Map Day [Reward] -> Reward -> IO (Map Day [Reward]))
-> Map Day [Reward] -> [Reward] -> IO (Map Day [Reward])
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM
                ( \Map Day [Reward]
acc Reward
r -> do
                    ZonedTime
rewardTime <- UTCTime -> IO ZonedTime
utcToLocalZonedTime (UTCTime -> IO ZonedTime) -> UTCTime -> IO ZonedTime
forall a b. (a -> b) -> a -> b
$ Reward -> UTCTime
rRewardTime Reward
r
                    Map Day [Reward] -> IO (Map Day [Reward])
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Map Day [Reward] -> IO (Map Day [Reward]))
-> Map Day [Reward] -> IO (Map Day [Reward])
forall a b. (a -> b) -> a -> b
$
                        ([Reward] -> [Reward] -> [Reward])
-> Day -> [Reward] -> Map Day [Reward] -> Map Day [Reward]
forall k a. Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
M.insertWith
                            [Reward] -> [Reward] -> [Reward]
forall a. Semigroup a => a -> a -> a
(<>)
                            (LocalTime -> Day
localDay (LocalTime -> Day) -> LocalTime -> Day
forall a b. (a -> b) -> a -> b
$ ZonedTime -> LocalTime
zonedTimeToLocalTime ZonedTime
rewardTime)
                            [Reward
r]
                            Map Day [Reward]
acc
                )
                Map Day [Reward]
forall k a. Map k a
M.empty
    aggregate :: [Reward] -> Maybe Reward
    aggregate :: [Reward] -> Maybe Reward
aggregate = \case
        [] -> Maybe Reward
forall a. Maybe a
Nothing
        [Reward]
rs ->
            Reward -> Maybe Reward
forall a. a -> Maybe a
Just (Reward -> Maybe Reward) -> Reward -> Maybe Reward
forall a b. (a -> b) -> a -> b
$
                Reward
                    { rValidatorName :: Text
rValidatorName =
                        Text
"AGGREGATE-"
                            Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
T.intercalate
                                Text
"-"
                                ([Text] -> [Text]
forall a. Ord a => [a] -> [a]
L.sort ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ (Reward -> Text) -> [Reward] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Reward -> Text
rValidatorName [Reward]
rs)
                    , rValidatorAddress :: Text
rValidatorAddress = Text
"AGGREGATE-" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Int -> String
forall a. Show a => a -> String
show (Int -> String) -> Int -> String
forall a b. (a -> b) -> a -> b
$ [Reward] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Reward]
rs)
                    , rDelegator :: Text
rDelegator = Text -> [Text] -> Text
T.intercalate Text
"-" ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ [Text] -> [Text]
forall a. Ord a => [a] -> [a]
L.sort ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ (Reward -> Text) -> [Reward] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Reward -> Text
rDelegator [Reward]
rs
                    , rChainId :: Text
rChainId = Reward -> Text
rChainId (Reward -> Text) -> Reward -> Text
forall a b. (a -> b) -> a -> b
$ [Reward] -> Reward
forall a. HasCallStack => [a] -> a
head [Reward]
rs
                    , rHeight :: Integer
rHeight = Reward -> Integer
rHeight (Reward -> Integer) -> Reward -> Integer
forall a b. (a -> b) -> a -> b
$ [Reward] -> Reward
forall a. HasCallStack => [a] -> a
head [Reward]
rs
                    , rReward :: Scientific
rReward = [Scientific] -> Scientific
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([Scientific] -> Scientific) -> [Scientific] -> Scientific
forall a b. (a -> b) -> a -> b
$ (Reward -> Scientific) -> [Reward] -> [Scientific]
forall a b. (a -> b) -> [a] -> [b]
map Reward -> Scientific
rReward [Reward]
rs
                    , rRewardTime :: UTCTime
rRewardTime = [UTCTime] -> UTCTime
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum ([UTCTime] -> UTCTime) -> [UTCTime] -> UTCTime
forall a b. (a -> b) -> a -> b
$ (Reward -> UTCTime) -> [Reward] -> [UTCTime]
forall a b. (a -> b) -> [a] -> [b]
map Reward -> UTCTime
rRewardTime [Reward]
rs
                    }
    filterByYear :: Integer -> [Reward] -> IO [Reward]
    filterByYear :: Integer -> [Reward] -> IO [Reward]
filterByYear Integer
year = (Reward -> IO Bool) -> [Reward] -> IO [Reward]
forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM ((Reward -> IO Bool) -> [Reward] -> IO [Reward])
-> (Reward -> IO Bool) -> [Reward] -> IO [Reward]
forall a b. (a -> b) -> a -> b
$ \Reward
reward -> do
        ZonedTime
rewardTime <- UTCTime -> IO ZonedTime
utcToLocalZonedTime (UTCTime -> IO ZonedTime) -> UTCTime -> IO ZonedTime
forall a b. (a -> b) -> a -> b
$ Reward -> UTCTime
rRewardTime Reward
reward
        Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return
            (Bool -> IO Bool) -> (LocalTime -> Bool) -> LocalTime -> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (\(Integer
y, Int
_, Int
_) -> Integer
y Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
year)
            ((Integer, Int, Int) -> Bool)
-> (LocalTime -> (Integer, Int, Int)) -> LocalTime -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Day -> (Integer, Int, Int)
toGregorian
            (Day -> (Integer, Int, Int))
-> (LocalTime -> Day) -> LocalTime -> (Integer, Int, Int)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LocalTime -> Day
localDay
            (LocalTime -> IO Bool) -> LocalTime -> IO Bool
forall a b. (a -> b) -> a -> b
$ ZonedTime -> LocalTime
zonedTimeToLocalTime ZonedTime
rewardTime


-- | CLI arguments supported by the executable.
data Args = Args
    { Args -> String
argPubKey :: String
    -- ^ BinanceChain account's pubkey.
    , Args -> Maybe String
argOutputFile :: Maybe String
    -- ^ Optional output file. 'Nothing' or @'Just' "-"@ will print to
    -- 'System.IO.stdout'.
    , Args -> Bool
argCoinTracking :: Bool
    -- ^ Flag to enable writing/printing files formatted for CoinTracking
    -- Bulk Imports.
    , Args -> Maybe Integer
argYear :: Maybe Integer
    -- ^ Year for limiting the output.
    , Args -> Bool
argAggregate :: Bool
    -- ^ Aggregate rewards into day buckets.
    }
    deriving (Int -> Args -> ShowS
[Args] -> ShowS
Args -> String
(Int -> Args -> ShowS)
-> (Args -> String) -> ([Args] -> ShowS) -> Show Args
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Args -> ShowS
showsPrec :: Int -> Args -> ShowS
$cshow :: Args -> String
show :: Args -> String
$cshowList :: [Args] -> ShowS
showList :: [Args] -> ShowS
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
$creadsPrec :: Int -> ReadS Args
readsPrec :: Int -> ReadS Args
$creadList :: ReadS [Args]
readList :: ReadS [Args]
$creadPrec :: ReadPrec Args
readPrec :: ReadPrec Args
$creadListPrec :: ReadPrec [Args]
readListPrec :: ReadPrec [Args]
Read, Args -> Args -> Bool
(Args -> Args -> Bool) -> (Args -> Args -> Bool) -> Eq Args
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Args -> Args -> Bool
== :: Args -> Args -> Bool
$c/= :: Args -> Args -> Bool
/= :: Args -> Args -> Bool
Eq, Typeable Args
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 -> Constr
Args -> DataType
(forall b. Data b => b -> b) -> Args -> 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)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Args -> c Args
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Args -> c Args
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Args
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Args
$ctoConstr :: Args -> Constr
toConstr :: Args -> Constr
$cdataTypeOf :: Args -> DataType
dataTypeOf :: Args -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Args)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Args)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Args)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Args)
$cgmapT :: (forall b. Data b => b -> b) -> Args -> Args
gmapT :: (forall b. Data b => b -> b) -> Args -> Args
$cgmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Args -> r
gmapQl :: forall r r'.
(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
gmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Args -> r
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Args -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> Args -> [u]
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Args -> u
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Args -> u
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Args -> m Args
gmapM :: forall (m :: * -> *).
Monad m =>
(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
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(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
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Args -> m 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
        { argPubKey :: String
argPubKey = 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
"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"
        , argYear :: Maybe Integer
argYear =
            Maybe Integer
forall a. Maybe a
Nothing
                Maybe Integer -> Ann -> Maybe Integer
forall val. Data val => val -> Ann -> val
&= String -> Ann
help String
"Limit to given year"
                Maybe Integer -> Ann -> Maybe Integer
forall val. Data val => val -> Ann -> val
&= Ann
explicit
                Maybe Integer -> Ann -> Maybe Integer
forall val. Data val => val -> Ann -> val
&= String -> Ann
name String
"y"
                Maybe Integer -> Ann -> Maybe Integer
forall val. Data val => val -> Ann -> val
&= String -> Ann
name String
"year"
                Maybe Integer -> Ann -> Maybe Integer
forall val. Data val => val -> Ann -> val
&= String -> Ann
typ String
"YYYY"
        , argAggregate :: Bool
argAggregate =
            Bool
False
                Bool -> Ann -> Bool
forall val. Data val => val -> Ann -> val
&= String -> Ann
help String
"Output one aggregate row per day."
                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
"aggregate"
        }
        Args -> Ann -> Args
forall val. Data val => val -> Ann -> val
&= String -> Ann
summary
            ( String
"bnb-staking-csvs v"
                String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Version -> String
showVersion Version
version
                String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
", Pavan Rikhi 2021-2024"
            )
        Args -> Ann -> Args
forall val. Data val => val -> Ann -> val
&= String -> Ann
program String
"bnb-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 you BinanceChain Staking Rewards."