From 1b91177a46fdc49897ca0b71ca502e27767ffca3 Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Fri, 9 Feb 2024 16:18:48 -0600 Subject: [PATCH] CLI enhancements to manage lists of items --- CHANGELOG.md | 9 ++++ app/Main.hs | 4 +- package.yaml | 5 ++ src/Zenith/CLI.hs | 129 +++++++++++++++++++++++++++++++++++++++++---- src/Zenith/Core.hs | 12 +++++ src/Zenith/DB.hs | 5 +- stack.yaml | 4 +- stack.yaml.lock | 12 ++--- zenith.cabal | 6 +++ zenith.cfg | 1 + 10 files changed, 166 insertions(+), 21 deletions(-) create mode 100644 src/Zenith/Core.hs diff --git a/CHANGELOG.md b/CHANGELOG.md index 490447a..0035626 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +## Added + +- `Core` module +- `CLI` module +- `DB` module +- Command line arguments to switch to legacy version + ## [0.4.1] ### Fixed diff --git a/app/Main.hs b/app/Main.hs index 764bcd9..f0faf47 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -2,7 +2,6 @@ module Main where -import Brick (simpleMain) import Control.Monad (void) import Control.Monad.IO.Class (liftIO) import qualified Data.ByteString as B @@ -200,6 +199,7 @@ main :: IO () main = do config <- load ["zenith.cfg"] args <- getArgs + dbName <- require config "dbName" nodeUser <- require config "nodeUser" nodePwd <- require config "nodePwd" if not (null args) @@ -215,7 +215,7 @@ main = do " ______ _ _ _ \n |___ / (_) | | | \n / / ___ _ __ _| |_| |__ \n / / / _ \\ '_ \\| | __| '_ \\ \n / /_| __/ | | | | |_| | | |\n /_____\\___|_| |_|_|\\__|_| |_|\n Zcash Full Node CLI v0.4.0" } (root nodeUser nodePwd) - "cli" -> simpleMain ui + "cli" -> runZenithCLI dbName _ -> printUsage else printUsage diff --git a/package.yaml b/package.yaml index 9e0bca8..d986cc6 100644 --- a/package.yaml +++ b/package.yaml @@ -44,6 +44,11 @@ library: - persistent-sqlite - persistent-template - brick + - mtl + - microlens + - microlens-mtl + - microlens-th + - vty - zcash-haskell executables: diff --git a/src/Zenith/CLI.hs b/src/Zenith/CLI.hs index 59df1a8..3617afa 100644 --- a/src/Zenith/CLI.hs +++ b/src/Zenith/CLI.hs @@ -1,13 +1,122 @@ +{-# LANGUAGE TemplateHaskell #-} + module Zenith.CLI where -import Brick (Widget, (<+>), joinBorders, simpleMain, str, withBorderStyle) -import Brick.Widgets.Border (borderWithLabel, vBorder) -import Brick.Widgets.Border.Style (unicode) -import Brick.Widgets.Center (center) +import Control.Monad (void) +import Control.Monad.State (modify) +import Data.Maybe (fromMaybe) +import qualified Data.Text as T +import qualified Graphics.Vty as V +import Lens.Micro ((^.)) +import Lens.Micro.Mtl +import Lens.Micro.TH -ui :: Widget () -ui = - joinBorders $ - withBorderStyle unicode $ - borderWithLabel (str "Zenith") $ - (center (str "Addresses") <+> vBorder <+> center (str "Transactions")) +import qualified Brick.AttrMap as A +import qualified Brick.Main as M +import qualified Brick.Types as BT +import Brick.Types (Widget) +import Brick.Util (fg, on) +import qualified Brick.Widgets.Border as B +import Brick.Widgets.Border.Style (unicode) +import qualified Brick.Widgets.Center as C +import Brick.Widgets.Core + ( (<+>) + , hLimit + , joinBorders + , str + , vBox + , vLimit + , withAttr + , withBorderStyle + ) +import qualified Brick.Widgets.List as L +import qualified Data.Vector as Vec +import Zenith.Core + +data Name + = WList + | AList + | TList + deriving (Eq, Show, Ord) + +data State = State + { _network :: String + , _wallets :: L.List Name String + , _addresses :: L.List Name String + , _transactions :: L.List Name String + } deriving (Show) + +makeLenses ''State + +drawUI :: State -> [Widget Name] +drawUI s = [ui s] + where + ui :: State -> Widget Name + ui s = + joinBorders $ + withBorderStyle unicode $ + B.borderWithLabel (str $ "Zenith - " <> s ^. network) $ + (C.center (listBox "Addresses" (s ^. addresses)) <+> + B.vBorder <+> C.center (listBox "Transactions" (s ^. transactions))) + listBox :: String -> L.List Name String -> Widget Name + listBox titleLabel l = + C.vCenter $ + vBox + [ C.hCenter + (B.borderWithLabel (str titleLabel) $ + hLimit 25 $ vLimit 15 $ L.renderList listDrawElement True l) + , str " " + , C.hCenter $ str "Select " + ] + +listDrawElement :: (Show a) => Bool -> a -> Widget Name +listDrawElement sel a = + let selStr s = + if sel + then withAttr customAttr (str $ "<" <> s <> ">") + else str s + in C.hCenter $ selStr $ show a + +initialState :: State +initialState = + State + "Main" + (L.list WList (Vec.fromList ["wall1"]) 1) + (L.list AList (Vec.fromList ["addr1", "addr2"]) 1) + (L.list TList (Vec.fromList ["tx1", "tx2", "tx3"]) 1) + +customAttr :: A.AttrName +customAttr = L.listSelectedAttr <> A.attrName "custom" + +appEvent :: BT.BrickEvent Name e -> BT.EventM Name State () +appEvent (BT.VtyEvent e) = + case e of + V.EvKey V.KEsc [] -> M.halt + ev -> BT.zoom addresses $ L.handleListEvent ev + +theMap :: A.AttrMap +theMap = + A.attrMap + V.defAttr + [ (L.listAttr, V.white `on` V.blue) + , (L.listSelectedAttr, V.blue `on` V.white) + , (customAttr, fg V.cyan) + ] + +theApp :: M.App State e Name +theApp = + M.App + { M.appDraw = drawUI + , M.appChooseCursor = M.showFirstCursor + , M.appHandleEvent = appEvent + , M.appStartEvent = return () + , M.appAttrMap = const theMap + } + +runZenithCLI :: T.Text -> IO () +runZenithCLI dbName = do + w <- checkWallets dbName + if (null w) + then void $ M.defaultMain theApp initialState + else do + print "No wallet found. Create one? Y/N" diff --git a/src/Zenith/Core.hs b/src/Zenith/Core.hs new file mode 100644 index 0000000..1356300 --- /dev/null +++ b/src/Zenith/Core.hs @@ -0,0 +1,12 @@ +module Zenith.Core where + +import qualified Data.Text as T +import Database.Persist +import Database.Persist.Sqlite +import Zenith.DB + +checkWallets :: T.Text -> IO [Entity ZcashWallet] +checkWallets dbName = do + runSqlite dbName $ do runMigration migrateAll + wallets <- runSqlite dbName $ selectList [ZcashWalletBirthdayHeight >. 0] [] + return wallets diff --git a/src/Zenith/DB.hs b/src/Zenith/DB.hs index fea47ca..97bdf55 100644 --- a/src/Zenith/DB.hs +++ b/src/Zenith/DB.hs @@ -21,7 +21,9 @@ import qualified Data.Text as T import Database.Persist import Database.Persist.Sqlite import Database.Persist.TH -import ZcashHaskell.Types (Phrase) +import ZcashHaskell.Types (Phrase, ZcashNet) + +derivePersistField "ZcashNet" share [mkPersist sqlSettings, mkMigrate "migrateAll"] @@ -32,5 +34,6 @@ share tPrivateKey BS.ByteString birthdayHeight Int name T.Text + network ZcashNet deriving Show |] diff --git a/stack.yaml b/stack.yaml index 7ed8d55..46515d8 100644 --- a/stack.yaml +++ b/stack.yaml @@ -44,9 +44,9 @@ packages: # extra-deps: [] extra-deps: - git: https://git.vergara.tech/Vergara_Tech/zcash-haskell.git - commit: 6ea8698ccb5e44f9900ba0e61c6ffe6cba900139 + commit: c4f345b1deb876e19a51c5f7ae1b4402fae14126 - git: https://git.vergara.tech/Vergara_Tech/haskell-hexstring.git - commit: fe2df6f7d63272ac147911c1573550bed1d38a37 + commit: fd1ddce73c0ad18a2a4509a299c6e93f8c6c383d - git: https://git.vergara.tech/Vergara_Tech/haskell-foreign-rust.git commit: 787c2e813eb3a5d16c375d4b37dfefbd2adcdf05 - git: https://github.com/well-typed/borsh.git diff --git a/stack.yaml.lock b/stack.yaml.lock index 6b91d93..0d86d36 100644 --- a/stack.yaml.lock +++ b/stack.yaml.lock @@ -5,26 +5,26 @@ packages: - completed: - commit: 6ea8698ccb5e44f9900ba0e61c6ffe6cba900139 + commit: c4f345b1deb876e19a51c5f7ae1b4402fae14126 git: https://git.vergara.tech/Vergara_Tech/zcash-haskell.git name: zcash-haskell pantry-tree: - sha256: 0506f9f095dbb134a4e7b3ba73a60a21c6298cbea01409871141b31cd0cf9c46 + sha256: 1bf709484bc488e51e18aa11001abdc06100ed7086b9bbd765d28c4a3d8e9113 size: 1366 version: 0.4.1 original: - commit: 6ea8698ccb5e44f9900ba0e61c6ffe6cba900139 + commit: c4f345b1deb876e19a51c5f7ae1b4402fae14126 git: https://git.vergara.tech/Vergara_Tech/zcash-haskell.git - completed: - commit: fe2df6f7d63272ac147911c1573550bed1d38a37 + commit: fd1ddce73c0ad18a2a4509a299c6e93f8c6c383d git: https://git.vergara.tech/Vergara_Tech/haskell-hexstring.git name: hexstring pantry-tree: - sha256: 71f12a60e85f7e1897b07bb2d4c77794faee50df250d68b0c47b3d343dd4625a + sha256: 05af6ec085b0c8ac00e0c3043652095a6a9c9d3bd2112ffdcb4c4e28206e0b1c size: 741 version: 0.12.0 original: - commit: fe2df6f7d63272ac147911c1573550bed1d38a37 + commit: fd1ddce73c0ad18a2a4509a299c6e93f8c6c383d git: https://git.vergara.tech/Vergara_Tech/haskell-hexstring.git - completed: commit: 787c2e813eb3a5d16c375d4b37dfefbd2adcdf05 diff --git a/zenith.cabal b/zenith.cabal index e8a98e3..66e50e1 100644 --- a/zenith.cabal +++ b/zenith.cabal @@ -26,6 +26,7 @@ source-repository head library exposed-modules: Zenith.CLI + Zenith.Core Zenith.DB Zenith.Types Zenith.Utils @@ -44,6 +45,10 @@ library , bytestring , http-conduit , http-types + , microlens + , microlens-mtl + , microlens-th + , mtl , persistent , persistent-sqlite , persistent-template @@ -54,6 +59,7 @@ library , scientific , text , vector + , vty , zcash-haskell default-language: Haskell2010 diff --git a/zenith.cfg b/zenith.cfg index e1d4a4f..77461ba 100644 --- a/zenith.cfg +++ b/zenith.cfg @@ -1,2 +1,3 @@ nodeUser = "user" nodePwd = "superSecret" +dbName = "zenith.db"