From 7956a2ec22d9cd783ece25c66b69112d9d389fad Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Thu, 27 Jun 2024 09:19:26 -0500 Subject: [PATCH] Add TX display --- assets/1F928_color.png | Bin 0 -> 10499 bytes src/Zenith/GUI.hs | 158 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 144 insertions(+), 14 deletions(-) create mode 100644 assets/1F928_color.png diff --git a/assets/1F928_color.png b/assets/1F928_color.png new file mode 100644 index 0000000000000000000000000000000000000000..10095c0e990dcdd729d94786f747148a85b780d1 GIT binary patch literal 10499 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 O2PmN+Uh~r^=>Gu`SjUe5 literal 0 HcmV?d00001 diff --git a/src/Zenith/GUI.hs b/src/Zenith/GUI.hs index 7b01f6b..cb3b28f 100644 --- a/src/Zenith/GUI.hs +++ b/src/Zenith/GUI.hs @@ -11,7 +11,8 @@ import Control.Exception (throwIO, try) import Control.Monad.Logger (runNoLoggingT) import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as LBS -import Data.Maybe (fromMaybe, isJust) +import Data.HexString (toText) +import Data.Maybe (fromJust, fromMaybe, isJust, isNothing) import qualified Data.Text as T import qualified Data.Text.Encoding as E import Data.Time.Clock.POSIX (posixSecondsToUTCTime) @@ -22,7 +23,9 @@ import Lens.Micro.TH import Monomer import qualified Monomer.Lens as L import System.Hclip -import TextShow +import Text.Wrap (FillScope(..), FillStrategy(..), WrapSettings(..), wrapText) +import TextShow hiding (toText) +import ZcashHaskell.Keys (generateWalletSeedPhrase) import ZcashHaskell.Orchard (getSaplingFromUA, isValidUnifiedAddress) import ZcashHaskell.Transparent (encodeTransparentReceiver) import ZcashHaskell.Types @@ -44,6 +47,7 @@ data AppEvent = AppInit | ShowMsg !T.Text | ShowError !T.Text + | ShowModal !T.Text | CloseMsg | WalletClicked | AccountClicked @@ -61,6 +65,7 @@ data AppEvent | LoadTxs ![Entity UserTx] | LoadAddrs ![Entity WalletAddress] | LoadAccs ![Entity ZcashAccount] + | LoadWallets ![Entity ZcashWallet] | ConfirmCancel | SaveAddress !(Maybe (Entity ZcashAccount)) | SaveAccount !(Maybe (Entity ZcashWallet)) @@ -68,6 +73,9 @@ data AppEvent | CloseSeed | ShowSeed | CopySeed !T.Text + | CopyTx !T.Text + | CloseTx + | ShowTx !Int deriving (Eq, Show) data AppModel = AppModel @@ -98,6 +106,8 @@ data AppModel = AppModel , _confirmEvent :: !AppEvent , _inError :: !Bool , _showSeed :: !Bool + , _modalMsg :: !(Maybe T.Text) + , _showTx :: !(Maybe Int) } deriving (Eq, Show) makeLenses ''AppModel @@ -135,6 +145,8 @@ buildUI wenv model = widgetTree , confirmOverlay `nodeVisible` isJust (model ^. confirmTitle) , seedOverlay `nodeVisible` model ^. showSeed , msgOverlay `nodeVisible` isJust (model ^. msg) + , txOverlay `nodeVisible` isJust (model ^. showTx) + , modalOverlay `nodeVisible` isJust (model ^. modalMsg) ] mainWindow = vstack @@ -383,7 +395,7 @@ buildUI wenv model = widgetTree (fromIntegral $ qrCodeWidth qr)) [fitWidth] Nothing -> - image_ "./assets/2620_color.png" [fitEither]) `styleBasic` + image_ "./assets/1F928_color.png" [fitEither]) `styleBasic` [bgColor white, height 100, width 100] , filler ] `styleBasic` @@ -418,7 +430,7 @@ buildUI wenv model = widgetTree txRow :: Int -> Entity UserTx -> WidgetNode AppModel AppEvent txRow idx tx = box_ - [onClick $ ShowMsg ("You clicked transaction " <> showt idx)] + [onClick $ ShowTx idx] (hstack [ label (T.pack $ @@ -515,6 +527,75 @@ buildUI wenv model = widgetTree , filler ] ] + modalOverlay = + box + (label (fromMaybe "?" $ model ^. modalMsg) `styleBasic` + [textSize 12, textFont "Bold"]) `styleBasic` + [bgColor (white & L.a .~ 0.5)] + txOverlay = + case model ^. showTx of + Nothing -> alert CloseTx $ label "N/A" + Just i -> + alert CloseTx $ + vstack + [ box_ + [alignLeft] + (hstack + [ label "Date " `styleBasic` [width 60, textFont "Bold"] + , separatorLine `styleBasic` [fgColor btnColor] + , spacer + , label + (T.pack $ + show $ + posixSecondsToUTCTime $ + fromIntegral $ + userTxTime $ entityVal $ (model ^. transactions) !! i) + ]) `styleBasic` + [padding 2, bgColor white, width 280, borderB 1 gray] + , box_ + [alignLeft] + (hstack + [ label "Tx ID " `styleBasic` [width 60, textFont "Bold"] + , separatorLine `styleBasic` [fgColor btnColor] + , spacer + , label_ + (txtWrap $ + toText $ + getHex $ + userTxHex $ entityVal $ (model ^. transactions) !! i) + [multiline] + , box_ + [] + (remixIcon remixFileCopyFill `styleBasic` + [textColor white]) `styleBasic` + [bgColor btnColor, radius 2] + ]) `styleBasic` + [padding 2, bgColor white, width 280, borderB 1 gray] + , box_ + [alignLeft] + (hstack + [ label "Amount" `styleBasic` [width 60, textFont "Bold"] + , separatorLine `styleBasic` [fgColor btnColor] + , spacer + , label $ + displayAmount (model ^. network) $ + fromIntegral $ + userTxAmount $ entityVal $ (model ^. transactions) !! i + ]) `styleBasic` + [padding 2, bgColor white, width 280, borderB 1 gray] + , box_ + [alignLeft] + (hstack + [ label "Memo " `styleBasic` [width 60, textFont "Bold"] + , separatorLine `styleBasic` [fgColor btnColor] + , spacer + , label_ + (txtWrap $ + userTxMemo $ entityVal $ (model ^. transactions) !! i) + [multiline] + ]) `styleBasic` + [padding 2, bgColor white, width 280, borderB 1 gray] + ] generateQRCodes :: Config -> IO () generateQRCodes config = do @@ -592,10 +673,11 @@ handleEvent :: -> [AppEventResponse AppModel AppEvent] handleEvent wenv node model evt = case evt of - AppInit -> [] + AppInit -> [Event NewWallet | isNothing currentWallet] ShowMsg t -> [Model $ model & msg ?~ t & menuPopup .~ False] ShowError t -> [Model $ model & msg ?~ t & menuPopup .~ False & inError .~ True] + ShowModal t -> [Model $ model & modalMsg ?~ t] WalletClicked -> [Model $ model & walPopup .~ True] AccountClicked -> [Model $ model & accPopup .~ True] MenuClicked -> [Model $ model & menuPopup .~ True] @@ -635,6 +717,7 @@ handleEvent wenv node model evt = SaveAddress acc -> if T.length (model ^. mainInput) > 1 then [ Task $ addNewAddress (model ^. mainInput) External acc + , Event $ ShowModal "Generating QR codes..." , Event ConfirmCancel ] else [Event $ ShowError "Invalid input", Event ConfirmCancel] @@ -645,13 +728,11 @@ handleEvent wenv node model evt = ] else [Event $ ShowError "Invalid input", Event ConfirmCancel] SaveWallet -> - [ if T.length (model ^. mainInput) > 1 - then Event $ ShowMsg $ "You saved wallet: " <> model ^. mainInput - else Event $ ShowError "Invalid input" - , Event ConfirmCancel - ] + if T.length (model ^. mainInput) > 1 + then [Task addNewWallet, Event ConfirmCancel] + else [Event $ ShowError "Invalid input"] SetPool p -> - [ Model $ model & selPool .~ p + [ Model $ model & selPool .~ p & modalMsg .~ Nothing , Task $ SwitchQr <$> do dbPool <- runNoLoggingT $ initPool $ c_dbPath $ model ^. configuration @@ -687,7 +768,8 @@ handleEvent wenv node model evt = Just wal -> runNoLoggingT $ getAccounts dbPool $ entityKey wal ] CopyAddr a -> - [ setClipboardData $ + [ setClipboardData ClipboardEmpty + , setClipboardData $ ClipboardText $ case model ^. selPool of Orchard -> maybe "None" (getUA . walletAddressUAddress . entityVal) a @@ -706,20 +788,35 @@ handleEvent wenv node model evt = , Event $ ShowMsg "Copied address!" ] CopySeed s -> - [ setClipboardData $ ClipboardText s + [ setClipboardData ClipboardEmpty + , setClipboardData $ ClipboardText s , Event $ ShowMsg "Copied seed phrase!" ] + CopyTx t -> + [ setClipboardData ClipboardEmpty + , setClipboardData $ ClipboardText t + , Event $ ShowMsg "Copied transaction ID!" + ] LoadTxs t -> [Model $ model & transactions .~ t] LoadAddrs a -> if not (null a) - then [Model $ model & addresses .~ a, Event $ SetPool Orchard] + then [ Model $ model & addresses .~ a + , Event $ SwitchAddr $ model ^. selAddr + , Event $ SetPool Orchard + ] else [Event $ NewAddress currentAccount] LoadAccs a -> if not (null a) then [Model $ model & accounts .~ a, Event $ SwitchAcc 0] else [Event $ NewAccount currentWallet] + LoadWallets a -> + if not (null a) + then [Model $ model & wallets .~ a, Event $ SwitchWal 0] + else [Event NewWallet] CloseMsg -> [Model $ model & msg .~ Nothing & inError .~ False] CloseSeed -> [Model $ model & showSeed .~ False] + CloseTx -> [Model $ model & showTx .~ Nothing] + ShowTx i -> [Model $ model & showTx ?~ i] where currentWallet = if null (model ^. wallets) @@ -781,6 +878,35 @@ handleEvent wenv node model evt = Just _x -> do aList <- runNoLoggingT $ getAccounts pool (entityKey w') return $ LoadAccs aList + addNewWallet :: IO AppEvent + addNewWallet = do + sP <- generateWalletSeedPhrase + pool <- runNoLoggingT $ initPool $ c_dbPath $ model ^. configuration + bc <- + try $ + checkBlockChain + (c_zebraHost $ model ^. configuration) + (c_zebraPort $ model ^. configuration) :: IO + (Either IOError ZebraGetBlockChainInfo) + case bc of + Left e1 -> return $ ShowError $ T.pack $ show e1 + Right chainInfo -> do + r <- + saveWallet pool $ + ZcashWallet + (model ^. mainInput) + (ZcashNetDB (model ^. network)) + (PhraseDB sP) + (zgb_blocks chainInfo) + 0 + case r of + Nothing -> return $ ShowError "Wallet already exists" + Just _ -> do + wL <- getWallets pool (model ^. network) + return $ LoadWallets wL + +txtWrap :: T.Text -> T.Text +txtWrap = wrapText (WrapSettings False True NoFill FillAfterFirst) 32 runZenithGUI :: Config -> IO () runZenithGUI config = do @@ -848,6 +974,8 @@ runZenithGUI config = do else Nothing) False False + Nothing + Nothing startApp model handleEvent buildUI params Left e -> do initDb dbFilePath @@ -882,6 +1010,8 @@ runZenithGUI config = do (SaveAddress Nothing) False False + Nothing + Nothing startApp model handleEvent buildUI params where params =