haskoin-wallet-0.2.0: Network/Haskoin/Wallet/Settings.hs
module Network.Haskoin.Wallet.Settings
( SPVMode(..)
, OutputFormat(..)
, Config(..)
) where
import Control.Monad (forM, mzero)
import Control.Exception (throw)
import Control.Monad.Logger (LogLevel(..))
import Data.Default (Default, def)
import Data.FileEmbed (embedFile)
import Data.Yaml (decodeEither')
import Data.Word (Word32, Word64)
import Data.HashMap.Strict (HashMap)
import qualified Data.Traversable as V (mapM)
import qualified Data.ByteString as BS (ByteString)
import qualified Data.Text as T (Text)
import Data.Aeson
( Value(..)
, FromJSON
, parseJSON
, withObject
, (.:), (.:?), (.!=)
)
import Network.Haskoin.Wallet.Database
import Network.Haskoin.Wallet.Types
data SPVMode = SPVOnline | SPVOffline
deriving (Eq, Show, Read)
data OutputFormat
= OutputNormal
| OutputJSON
| OutputYAML
data Config = Config
{ configKeyRing :: !T.Text
-- ^ Keyring to use in commands
, configCount :: !Word32
-- ^ Output size of commands
, configMinConf :: !Word32
-- ^ Minimum number of confirmations
, configSignTx :: !Bool
-- ^ Sign transactions
, configFee :: !Word64
-- ^ Fee to pay per 1000 bytes when creating new transactions
, configRcptFee :: !Bool
-- ^ Recipient pays fee (dangerous, no config file setting)
, configAddrType :: !AddressType
-- ^ Return internal instead of external addresses
, configOffline :: !Bool
-- ^ Display the balance including offline transactions
, configReversePaging :: !Bool
-- ^ Use reverse paging for displaying addresses and transactions
, configPass :: !(Maybe T.Text)
-- ^ Passphrase to use when creating new keyrings (bip39 mnemonic)
, configFormat :: !OutputFormat
-- ^ How to format the command-line results
, configConnect :: !String
-- ^ ZeroMQ socket to connect to (location of the server)
, configDetach :: !Bool
-- ^ Detach server when launched from command-line
, configFile :: !FilePath
-- ^ Configuration file
, configTestnet :: !Bool
-- ^ Use Testnet3 network
, configDir :: !FilePath
-- ^ Working directory
, configBind :: !String
-- ^ Bind address for the zeromq socket
, configBTCNodes :: !(HashMap T.Text [(String, Int)])
-- ^ Trusted Bitcoin full nodes to connect to
, configMode :: !SPVMode
-- ^ Operation mode of the SPV node.
, configBloomFP :: !Double
-- ^ False positive rate for the bloom filter.
, configDatabase :: !(HashMap T.Text DatabaseConfType)
-- ^ Database configuration
, configLogFile :: !FilePath
-- ^ Log file
, configPidFile :: !FilePath
-- ^ PID File
, configLogLevel :: !LogLevel
-- ^ Log level
, configVerbose :: !Bool
-- ^ Verbose
}
configBS :: BS.ByteString
configBS = $(embedFile "config/config.yml")
instance Default Config where
def = either throw id $ decodeEither' configBS
instance FromJSON Config where
parseJSON = withObject "Config" $ \o -> do
let configRcptFee = False
configFile = "config.yml"
configPass = Nothing
configKeyRing <- o .:? "keyring-name"
.!= configKeyRing def
configCount <- o .:? "output-size"
.!= configCount def
configMinConf <- o .:? "minimum-confirmations"
.!= configMinConf def
configSignTx <- o .:? "sign-transactions"
.!= configSignTx def
configFee <- o .:? "transaction-fee"
.!= configFee def
configAddrType <- k =<< o .:? "address-type"
configOffline <- o .:? "offline"
.!= configOffline def
configReversePaging <- o .:? "reverse-paging"
.!= configReversePaging def
configFormat <- f =<< o .:? "display-format"
configConnect <- o .:? "connect-uri"
.!= configConnect def
configDetach <- o .:? "detach-server"
.!= configDetach def
configTestnet <- o .:? "use-testnet"
.!= configTestnet def
configDir <- o .:? "work-dir"
.!= configDir def
configBind <- o .:? "bind-socket"
.!= configBind def
configBTCNodes <- g =<< o .:? "bitcoin-full-nodes"
configMode <- h =<< o .:? "server-mode"
configBloomFP <- o .:? "bloom-false-positive"
.!= configBloomFP def
configDatabase <- i =<< o .:? "database"
configLogFile <- o .:? "log-file"
.!= configLogFile def
configPidFile <- o .:? "pid-file"
.!= configPidFile def
configLogLevel <- j =<< o .:? "log-level"
configVerbose <- o .:? "verbose"
.!= configVerbose def
return Config {..}
where
f format = case format of
Just (String "normal") -> return OutputNormal
Just (String "json") -> return OutputJSON
Just (String "yaml") -> return OutputYAML
Just _ -> mzero
Nothing -> return $ configFormat def
g (Just x) = flip (withObject "btcnodesobj") x $ V.mapM $ \a -> do
ls <- parseJSON a
forM ls $ withObject "bitcoinnode" $ \o ->
(,) <$> (o .: "host") <*> (o .: "port")
g Nothing = return $ configBTCNodes def
h mode = case mode of
Just (String "online") -> return SPVOnline
Just (String "offline") -> return SPVOffline
Just _ -> mzero
Nothing -> return $ configMode def
i (Just x) = flip (withObject "databases") x $ V.mapM .
withObject "database" $ \v -> v .: databaseEngine
i Nothing = return $ configDatabase def
j level = case level of
Just (String "debug") -> return LevelDebug
Just (String "info") -> return LevelInfo
Just (String "warn") -> return LevelWarn
Just (String "error") -> return LevelError
Just _ -> mzero
Nothing -> return $ configLogLevel def
k addrtype = case addrtype of
Just (String "internal") -> return AddressInternal
Just (String "external") -> return AddressExternal
Just _ -> mzero
Nothing -> return $ configAddrType def